0.1 Plot the covariances across the genome

#Find the regions with a high temporal covariance 
pops<-c("PWS","TB","SS")
winsize<-c("50k","75k","100k")
evens<-paste0("chr",seq(2,26, by=2))
cov.list<-list()
covs_all<-list()
k=1
for (p in 1: length(pops)){
    pop<-pops[p]
    for (i in 1: length(winsize)){
        iv<-read.csv(paste0("~/Projects/Pacherring_Vincent/MD7000/3pops_intervals_",winsize[i],"window.csv"), row.names = 1)
        if (p==3) {
            cov23<-read.csv(paste0("~/Projects/Pacherring_Vincent/MD7000/",pop,"_cov23_2017-2006_2006-1996_3Pops_",winsize[i],"window.csv"), header = F)
            covs<-cbind(iv, cov23)
            colnames(covs)[4]<-c("cov23")
            covs$index=1:nrow(covs)
            covs$color<-"col1"
            covs$color[covs$chrom %in% evens]<-"col2"
    
            covs[sapply(covs, is.infinite)] <- NA
            covs[sapply(covs, is.nan)] <- NA
            
            cov.list[[k]]<-covs
            names(cov.list)[k]<-paste0(pop,"_",winsize[i])    
            k=k+1
            
            y<-min(covs$cov23, na.rm=T)
            ymin<-ifelse (y<=-0.1,-0.1, y) 
            ymax<-max(covs$cov23, na.rm=T)
            ggplot(covs, aes(x=index, y=cov23, color=color))+
                geom_point(size=1, alpha=0.5)+
                theme_classic()+
                ylim(ymin,ymax)+
                scale_color_manual(values=c("gray70","steelblue"), guide="none")+
                ylab("Covariance")+xlab('Chromosome')+
                theme(axis.text.x = element_blank())+
                ggtitle(paste0(pop," ", winsize[i]," window"))
            #ggsave(paste0("../Output/COV/3Pops.",pop,"_tempCovs_acrossGenome_",winsize[i], "Window.png"), width = 8, height = 2.7, dpi=300) 
        }
        else {
            cov12<-read.csv(paste0("~/Projects/Pacherring_Vincent/MD7000/",pop,"_cov12_1996-1991_2006-1996_3Pops_",winsize[i],"window.csv"), header = F)
            cov23<-read.csv(paste0("~/Projects/Pacherring_Vincent/MD7000/",pop,"_cov23_2017-2006_2006-1996_3Pops_",winsize[i],"window.csv"), header = F)
            cov13<-read.csv(paste0("~/Projects/Pacherring_Vincent/MD7000/",pop,"_cov13_2017-2006_1996-1991_3Pops_",winsize[i],"window.csv"), header = F)
            covs<-cbind(iv, cov12, cov23,cov13)
            colnames(covs)[4:6]<-c("cov12","cov23","cov13")
            covs$index=1:nrow(covs)
    
            covs$color<-"col1"
            covs$color[covs$chrom %in% evens]<-"col2"
    
            covs[sapply(covs, is.infinite)] <- NA
            covs[sapply(covs, is.nan)] <- NA
            
            cov.list[[k]]<-covs
            names(cov.list)[k]<-paste0(pop,"_",winsize[i])    
            k=k+1
            covsm<-melt(covs[,c("index","color","cov12","cov23","cov13")], id.vars = c("index", "color"))
            ymax<-max(covsm$value, na.rm=T)
            y<-min(covsm$value, na.rm=T)
            ymin<-ifelse (y<=-0.1,-0.1, y) 
            ggplot(covsm, aes(x=index, y=value, color=color))+
                facet_wrap(~variable, nrow=3)+
                geom_point(size=1, alpha=0.5)+
                theme_classic()+
                ylim(ymin,ymax)+
                scale_color_manual(values=c("gray70","steelblue"), guide="none")+
                ylab("Covariance")+xlab('Chromosome')+
                theme(axis.text.x = element_blank())+
                ggtitle(paste0(pop," ", winsize[i]," window"))
            #ggsave(paste0("../Output/COV/3Pops.",pop,"_tempCovs_acrossGenome_",winsize[i], "Window.png"), width = 8, height = 8, dpi=300)    
        }
    }
}


0.2 Find the outlier regions for each time period

#find how outliers overlap between different windows
cov12<-data.frame()
cov23<-data.frame()
cov13<-data.frame()

for (i in 1:length(cov.list)){
 if (grepl("PWS",names(cov.list)[i])|grepl("TB",names(cov.list)[i])){
    covs<-cov.list[[i]]
    
    pop<-gsub("_.+",'', names(cov.list)[i])
    win<-gsub(paste0(pop,"_"), '', names(cov.list)[i])
    
    covs<-covs[order(covs$cov12, decreasing=T),]
    n<-ceiling(nrow(covs)*0.01) #top1% region
    covs12_top<-covs[1:n,c(1:4)]
    covs12_top<-covs12_top[order(covs12_top$chrom, covs12_top$start),]
    covs12_top$window<-win
    covs12_top$pop<-pop
    cov12<-rbind(cov12, covs12_top)
    
    covs<-covs[order(covs$cov13, decreasing=T),]
    n<-ceiling(nrow(covs)*0.01) #top1% region
    covs13_top<-covs[1:n,c(1:3,6)]
    covs13_top<-covs13_top[order(covs13_top$chrom, covs13_top$start),]
    covs13_top$window<-win
    covs13_top$pop<-pop
    cov13<-rbind(cov13, covs13_top)
    
    covs<-covs[order(covs$cov23, decreasing=T),]
    n<-ceiling(nrow(covs)*0.01) #top1% region
    covs23_top<-covs[1:n,c(1:3,5)]
    covs23_top<-covs23_top[order(covs23_top$chrom, covs23_top$start),]
    covs23_top$window<-win
    covs23_top$pop<-pop
    cov23<-rbind(cov23, covs23_top)
 }
 if (grepl("SS",names(cov.list)[i])){
    covs<-cov.list[[i]]
    
    pop<-gsub("_.+",'', names(cov.list)[i])
    win<-gsub(paste0(pop,"_"), '', names(cov.list)[i])
    
    covs<-covs[order(covs$cov23, decreasing=T),]
    n<-ceiling(nrow(covs)*0.01) #top1% region
    covs23_top<-covs[1:n,c(1:4)]
    covs23_top<-covs23_top[order(covs23_top$chrom, covs23_top$start),]
    covs23_top$window<-win
    covs23_top$pop<-pop
    cov23<-rbind(cov23, covs23_top)
    
    }
}


write.csv(cov12, "../Output/COV/3pops_top1percent_outlier_regions.cov12_new.csv",row.names = F)
write.csv(cov23, "../Output/COV/3pops_top1percent_outlier_regions.cov23_new.csv",row.names = F)
write.csv(cov13, "../Output/COV/3pops_top1percent_outlier_regions.cov13_new.csv",row.names = F)
#Create plots with different colors for outliers
#for COV12 and COV13 for TB and PWS (100K)
cv<-c("cov12","cov13","cov23")
winsize<-c("50k","75k","100k")

for (i in 1:length(cv)){
    if (i==1|i==2){
        for (w in 1: length(winsize)){
            #PWS
            df1<-cov.list[[paste0("PWS_", winsize[w])]]
            df1<-df1[order(df1[,cv[i]], decreasing=T),]
            n<-ceiling(nrow(df1)*0.01) #top1% region
            df1$top1<-"N"
            df1$top1[1:n]<-"PWS"
            
            #tb
            df2<-cov.list[[paste0("TB_", winsize[w])]]
            df2<-df2[order(df2[,cv[i]], decreasing=T),]
            df2$top1<-"N"
            df2$top1[1:n]<-"TB"
            
            co<-rbind(df1, df2)
    
            co$chrom<-factor(co$chrom, levels=paste0("chr", 1:26))
            co$top1<-factor(co$top1, levels=c("PWS","TB","N"))
            colnames(co)[which(colnames(co)==cv[i])]<-"cov"
    
            ymax<-max(co$cov, na.rm=T)
            ggplot(co, aes(x=start/1000000, y=cov, color=top1))+
                geom_point(size=0.5)+
                facet_wrap(~chrom, ncol=4)+
                theme_classic()+ylim(-0.1,ymax)+
                scale_color_manual(values=c("deeppink","orange" ,"#ADD8E680"), labels=c("PWS", "TB", ""))+
                ylab("Covariance")+xlab('Postion (Mb)')+
                ggtitle(paste0(winsize[w]," window ",cv[i]))+
                scale_x_continuous(labels = comma)+
                guides(color = guide_legend(override.aes = list(color=c("deeppink","orange","white")), title=element_text("Top 1%")))
   
                ggsave(paste0("../Output/COV/COVscan_3pop/3Pops.",cv[i],"_perChrom_",winsize[w], "Window_Outliers.png"), width = 10, height = 8, dpi=300)
        }
       
    }
   
    if (i==3){
        for (w in 1: length(winsize)){
        #pws
        df1<-cov.list[[paste0("PWS_", winsize[w])]]
        df1<-df1[,c("chrom","start","end","cov23")]
        df1<-df1[order(df1$cov23, decreasing=T),]
        n<-ceiling(nrow(df1)*0.01) #top1% region
        df1$top1<-"N"
        df1$top1[1:n]<-"PWS"
    
        #tb
        df2<-cov.list[[paste0("TB_", winsize[w])]]
        df2<-df2[,c("chrom","start","end","cov23")]
        df2<-df2[order(df2$cov23, decreasing=T),]
        df2$top1<-"N"
        df2$top1[1:n]<-"TB"
    
        #ss
        df3<-cov.list[[paste0("SS_", winsize[w])]]
        df3<-df3[,c("chrom","start","end","cov23")]
        df3<-df3[order(df3$cov23, decreasing=T),]
        df3$top1<-"N"
        df3$top1[1:n]<-"SS"

        co<-rbind(df1,df2,df3)

        co$chrom<-factor(co$chrom, levels=paste0("chr", 1:26))
        co$top1<-factor(co$top1, levels=c("PWS","TB","SS","N"))
        ymax<-max(co$cov23, na.rm=T)
        ggplot(co, aes(x=start/1000000, y=cov23, color=top1))+
            geom_point(size=0.5)+
            facet_wrap(~chrom, ncol=4)+
            theme_classic()+ylim(-0.1,ymax)+
            ylab("Covariance")+xlab('Postion (Mb)')+
            ggtitle(paste0(winsize[w]," window ",cv[i]))+
            scale_x_continuous(labels = comma)+
            #scale_color_discrete(breaks=c("PWS","SS","TB"))+
            scale_color_manual(values=c("deeppink","orange",gre,"#ADD8E666"), labels=c("PWS","TB","SS", ""))+
            guides(color = guide_legend(override.aes = list(color=c("deeppink","orange",gre,         "white")),title=element_text("Top 1% outliers"))) 
        ggsave(paste0("../Output/COV/COVscan_3pop/3Pops.cov23_3Pops_perChrom_",winsize[w], "Window_Outliers.png"), width = 10, height = 9, dpi=300)
        }
    }
}


0.2.1 Whole genome plots without facet wrap

cv<-c("cov12","cov13","cov23")
for (i in 1:length(cv)){
    if (i==1|i==2){
        df1<-cov.list[["PWS_100k"]]
        df1<-df1[order(df1[,cv[i]], decreasing=T),]
        n<-ceiling(nrow(df1)*0.01) #top1% region
        df1$top1<-"N"
        df1$top1[1:n]<-"PWS"
        
        df2<-cov.list[["TB_100k"]]
        df2<-df2[order(df2[,cv[i]], decreasing=T),]
        df2$top1<-"N"
        df2$top1[1:n]<-"TB"

        co<-rbind(df1, df2)
        co$chrom<-factor(co$chrom, levels=paste0("chr", 1:26))
        colnames(co)[which(colnames(co)==cv[i])]<-"cov"
        #assgin colors
        co$top1<-apply(co, 1, function(x) {ifelse (x['top1']=="N", x['color'], x['top1'])} )
        co$top1<-factor(co$top1, levels=c("PWS","TB","col1","col2"))
        
        #count the number of sites per chromosomes
        poss<-data.frame(chr=paste0("chr",1:26))
        k=1
        for (j in 1:26){
            df<-df1[df1$chr==paste0("chr",j),]
            poss$start[j]<-k
            poss$end[j]<-k+nrow(df)-1
            k=k+nrow(df)
        }
        poss$x<-poss$start+(poss$end-poss$start)/2
        ymax<-max(co$cov, na.rm=T)
        ggplot(co, aes(x=index, y=cov, color=top1))+
            geom_point(size=0.5)+
            theme_classic()+ylim(-0.1,ymax)+
            scale_color_manual(values=c("#FF3293B3","#0433FFB3" ,"#ADD8E680","#C0C0C088"), labels=c("PWS", "TB", "",""))+
                ylab("Covariance")+
                ggtitle(paste0(" 100k window ",cv[i]))+
                guides(color = guide_legend(override.aes = list(color=c("deeppink","#0433FF","white","white"), size=2), title=element_text("Outlier (1%)", size=10)))+
            scale_x_continuous(name="Chromosome", breaks=poss$x, labels=1:26)
        ggsave(paste0("../Output/COV/COVscan_3pop/3Pops.",cv[i],"_100k_Window_Outliers.png"), width = 10, height = 3.5, dpi=300)
        }}
    if (i==3){
        #pws
        df1<-cov.list[["PWS_100k"]]
        df1<-df1[,c("chrom","start","end","cov23","index","color")]
        df1<-df1[order(df1$cov23, decreasing=T),]
        n<-ceiling(nrow(df1)*0.01) #top1% region
        df1$top1<-df1$color
        df1$top1[1:n]<-"PWS"
        #tb
        df2<-cov.list[["TB_100k"]]
        df2<-df2[,c("chrom","start","end","cov23","index","color")]
        df2<-df2[order(df2$cov23, decreasing=T),]
        df2$top1<-df2$color
        df2$top1[1:n]<-"TB"
        #ss
        df3<-cov.list[["SS_100k"]]
        df3<-df3[,c("chrom","start","end","cov23","index","color")]
        df3<-df3[order(df3$cov23, decreasing=T),]
        df3$top1<-df3$color
        df3$top1[1:n]<-"SS"

        co<-rbind(df1,df2,df3)
        co$top1<-factor(co$top1, levels=c("PWS","TB","SS","col1","col2"))
        
        #count the number of sites per chromosomes
        poss<-data.frame(chr=paste0("chr",1:26))
        k=1
        for (j in 1:26){
            df<-df1[df1$chr==paste0("chr",j),]
            poss$start[j]<-k
            poss$end[j]<-k+nrow(df)-1
            k=k+nrow(df)
        }
        poss$x<-poss$start+(poss$end-poss$start)/2
        ymax<-max(co$cov, na.rm=T)
        ggplot(co, aes(x=index, y=cov23, color=top1))+
            geom_point(size=0.5)+
            theme_classic()+ylim(-0.1,ymax)+
            scale_color_manual(values=c("#FF3293B3","#0433FFB3","#008F00B3" ,"#ADD8E680","#C0C0C088"), labels=c("PWS", "TB","SS", "",""))+
                ylab("Covariance")+
                ggtitle(paste0(" 100k window ",cv[i]))+
                guides(color = guide_legend(override.aes = list(color=c("deeppink","#0433FF","#008F00","white","white"), size=2), title=element_text("Outlier (1%)")))+
            scale_x_continuous(name="Chromosome", breaks=poss$x, labels=1:26)+
            theme(legend.title = element_text(size=10))
        ggsave(paste0("../Output/COV/COVscan_3pop/3Pops.",cv[i],"_100k_Window_Outliers.png"), width = 10, height = 3.5, dpi=300)
        }
    }
}

## Plot 3 time periods together for PWS and TB
Cov<-data.frame()
for (i in 1:length(cv)){
    df1<-cov.list[["PWS_100k"]]
    df1<-df1[order(df1[,cv[i]], decreasing=T),]
    n<-ceiling(nrow(df1)*0.01) #top1% region
    df1$top1<-"N"
    df1$top1[1:n]<-"PWS"
    
    df2<-cov.list[["TB_100k"]]
    df2<-df2[order(df2[,cv[i]], decreasing=T),]
    df2$top1<-"N"
    df2$top1[1:n]<-"TB"
    co<-rbind(df1, df2)
    co$chrom<-factor(co$chrom, levels=paste0("chr", 1:26))
    colnames(co)[which(colnames(co)==cv[i])]<-"cov"
    #assgin colors
    co$top1<-apply(co, 1, function(x) {ifelse (x['top1']=="N", x['color'], x['top1'])} )
    co$top1<-factor(co$top1, levels=c("PWS","TB","col1","col2"))
    co$time<-cv[i]
    
    Cov<-rbind(Cov, co[,c("index", "cov","top1","time")])
}

#count the number of sites per chromosomes
df1<-cov.list[["PWS_100k"]]
poss<-data.frame(chr=paste0("chr",1:26))
k=1
for (j in 1:26){
        df<-df1[df1$chr==paste0("chr",j),]
        poss$start[j]<-k
        poss$end[j]<-k+nrow(df)-1
        k=k+nrow(df)
}
poss$x<-poss$start+(poss$end-poss$start)/2
ymax<-max(co$cov, na.rm=T)
ggplot(Cov, aes(x=index, y=cov, color=top1))+
    facet_wrap(~time, ncol=1)+
    geom_point(size=0.5)+
    theme_classic()+ylim(-0.1,ymax)+
    scale_color_manual(values=c("#FF3293B3","#0433FFB3" ,"#ADD8E680","#C0C0C088"), labels=c("PWS", "TB", "",""))+
    ylab("Covariance")+
    guides(color = guide_legend(override.aes = list(color=c("deeppink","#0433FF","white","white"), size=2), title=element_text("Outlier (1%)", size=10)))+
    scale_x_continuous(name="Chromosome", breaks=poss$x, labels=1:26)

ggsave(paste0("../Output/COV/COVscan_3pop/PWS_TB_100k_Window_Outliers.png"), width = 11, height = 5, dpi=300)
        }}

0.3 Overlapping outlier regions between different window sizes (top1%)

# How window size affects outlier regions

#COV12
cv<-c("cov12","cov13","cov23")
winsize<-c("50k","75k","100k")
pairs<-t(combn(winsize, 2))
pairs<-data.frame(pairs)
colnames(pairs)<-paste0("window",1:2)
Ov1<-pairs
Ov2<-pairs
Ov3<-pairs
#populations<-c("PWS","TB")
for (i in 1:length(cv)){
    df<-read.csv(paste0("../Output/COV/3pops_top1percent_outlier_regions.", cv[i], "_new.csv"))
    df$id<-paste0(df$chrom,"_",df$start)
    pws<-df[df$pop=="PWS",]
    tb<-df[df$pop=="TB",]
    if (i==3) ss<-df[df$pop=="SS",]
        
    for(j in 1:nrow(pairs)){
        isec<-intersect(pws$id[pws$window==pairs[j,1]], pws$id[pws$window==pairs[j,2]]) 
        Ov1[j, cv[i]]<-length(isec)
        isec2<-intersect(tb$id[tb$window==pairs[j,1]], tb$id[tb$window==pairs[j,2]]) 
        Ov2[j, cv[i]]<-length(isec2)
        if (i==3) {
              isec3<-intersect(ss$id[ss$window==pairs[j,1]], ss$id[ss$window==pairs[j,2]]) 
              Ov3[j, cv[i]]<-length(isec3)
         }
        #### Check chromosome region overlap +-200,000 bases
        
        for(p in 1:length(pops)){
            if (p==1) df_pop<-pws
            if (p==2) df_pop<-tb
            if (p==3 & exists("ss")) {df_pop<-ss}
                else next
        
            time1<-df_pop[df_pop$window==pairs[j,1],]
            time2<-df_pop[df_pop$window==pairs[j,2],]
             
            overlps<-data.frame()
            overlps2<-data.frame()
        
            for (n in 1: nrow(time1)){
                re<-time2[time2$chrom==time1$chrom[n],]
                if (nrow(re)>=1){
                    for (s in 1: nrow(re)){
                        if (re$start[s]<=time1$start[n]+200000 & re$start[s]>=time1$start[n]-200000){
                            overlps<-rbind(overlps, re[s,])
                            overlps2<-rbind(overlps2,time1[n,])}
                }}
            }      
            #Overlapping windows:
            ov<-data.frame(id=overlps$id)
            for (n in 1: nrow(overlps)){
                if (overlps$start[n]<overlps2$start[n]) {ov$start[n]<-overlps$start[n]; ov$end[n]<-overlps2$end[n]}
                if (overlps$start[n]>=overlps2$start[n]) {ov$start[n]<-overlps2$start[n];ov$end[n]<-overlps$end[n]}
            }
            ov[,paste0("cov.",pairs[j,1])]<-overlps[,4]
            ov[,paste0("cov.",pairs[j,2])]<-overlps2[,4]
            write.csv(ov, paste0("../Output/COV/COVscan_3pop/Overlap_regions_",pops[p],".", pairs[j,1],".",pairs[j,2], ".",cv[i], "_plusminus200k.csv"), row.names = F)
        }
    }
}
write.csv(Ov1, paste0("../Output/COV/COVscan_3pop/Overlapping_window_counts_PWS.csv"))
write.csv(Ov2, paste0("../Output/COV/COVscan_3pop/Overlapping_window_counts_TB.csv"))
write.csv(Ov3, paste0("../Output/COV/COVscan_3pop/Overlapping_window_counts_SS.csv"))

0.4 Overlapping outlier regions between different populations

#100k
cv<-c("cov12","cov13","cov23")
pairs<-t(combn(pops, 2))
pairs<-data.frame(pairs)
colnames(pairs)<-paste0("pop",1:2)
Ov_direct<-data.frame(cov=c(cv[1:2],"cov23-PT","cov23-PS","cov23-ST" ,"cov23-3"))
Ov_300<-data.frame(cov=c(cv[1:2],"cov23-PT","cov23-PS","cov23-ST" ,"cov23-3"))
for (i in 1:length(cv)){
    df<-read.csv(paste0("../Output/COV/COVscan_3pop/3pops_top1percent_outlier_regions.", cv[i], "_new.csv"))
    df<-df[df$window=="100k",]
    df$id<-paste0(df$chrom,"_",df$start)
    
    if (i!=3){
        #exact overlaps
        isec<-intersect(df$id[df$pop=="PWS"], df$id[df$pop=="TB"]) 
        Ov_direct$count[i]<-length(isec)
        
        #### Check chromosome region overlap +-200,000 bases
        pop1<-df[df$pop=="PWS",]
        pop2<-df[df$pop=="TB",]
        overlps<-data.frame()
        overlps2<-data.frame()
        for (n in 1: nrow(pop1)){
            re<-pop2[pop2$chrom==pop1$chrom[n],]
            if (nrow(re)>=1){
                for (s in 1: nrow(re)){
                    if (re$start[s]<=pop1$start[n]+300000 & re$start[s]>=pop1$start[n]-300000){
                        overlps<-rbind(overlps, re[s,])
                        overlps2<-rbind(overlps2,pop1[n,])}
                }
            }
        }
        # Merge two tables into one summary overlap table:
        ov<-data.frame(id=overlps$id)
        for (n in 1: nrow(overlps)){
            if (overlps$start[n]<overlps2$start[n]) {ov$start[n]<-overlps$start[n]; ov$end[n]<-overlps2$end[n]}
            if (overlps$start[n]>=overlps2$start[n]) {ov$start[n]<-overlps2$start[n];ov$end[n]<-overlps$end[n]}
        }
        ov[,"cov.PWS"]<-overlps[,4]
        ov[,"cov.TB"]<-overlps2[,4]
        write.csv(ov, paste0("../Output/COV/COVscan_3pop/Overlap_regions_",cv[i],"_plusminus300k.csv"), row.names = F)
        Ov_300$count[i]<-nrow(ov)
        }
        
    if (i==3){
        isec<-intersect(df$id[df$pop=="PWS"], df$id[df$pop=="TB"]) 
        isec2<-intersect(df$id[df$pop=="PWS"], df$id[df$pop=="SS"]) 
        isec3<-intersect(df$id[df$pop=="SS"], df$id[df$pop=="TB"]) 
        Ov_direct$count[i]<-length(isec)
        Ov_direct$count[i+1]<-length(isec2)
        Ov_direct$count[i+2]<-length(isec)
        Ov_direct$count[i+3]<-length(intersect(df$id[df$pop=="SS"], intersect(df$id[df$pop=="PWS"], df$id[df$pop=="TB"])))
        
        for(j in 1:nrow(pairs)){
        #### Check chromosome region overlap +-200,000 bases
            pop1<-df[df$pop==pairs[j,1],]
            pop2<-df[df$pop==pairs[j,2],]
            overlps<-data.frame()
            overlps2<-data.frame()
            for (n in 1: nrow(pop1)){
                re<-pop2[pop2$chrom==pop1$chrom[n],]
                if (nrow(re)>=1){
                    for (s in 1: nrow(re)){
                        if (re$start[s]<=pop1$start[n]+300000 & re$start[s]>=pop1$start[n]-300000){
                            overlps<-rbind(overlps, re[s,])
                            overlps2<-rbind(overlps2,pop1[n,])}
                    }
                }
            }
        # Merge two tables into one summary overlap table:
            ov<-data.frame(id=overlps$id)
            for (n in 1: nrow(overlps)){
                if (overlps$start[n]<overlps2$start[n]) {ov$start[n]<-overlps$start[n]; ov$end[n]<-overlps2$end[n]}
                if (overlps$start[n]>=overlps2$start[n]) {ov$start[n]<-overlps2$start[n];ov$end[n]<-overlps$end[n]}
            }
        
            ov[,paste0("cov.",pairs[j,1])]<-overlps[,4]
            ov[,paste0("cov.",pairs[j,2])]<-overlps2[,4]
            ov<-ov[!duplicated(ov),]
            write.csv(ov, paste0("../Output/COV/COVscan_3pop/Overlap_regions_",cv[i],"_",pairs[j,1],".", pairs[j,2],"_plusminus300k.csv"), row.names = F)
            Ov_300$count[i+j-1]<-nrow(ov)
    }
    }
}
write.csv(Ov_direct, paste0("../Output/COV/COVscan_3pop/DDirect_Overlapping_regions_counts_3pop_summary.csv"))
Ov_300$count[6]<-NA
write.csv(Ov_300, paste0("../Output/COV/COVscan_3pop/Overlapping_regions_counts_3pop_plusMinus300k.csv"))

1 Run the snpEff pipeline to find annotation in the outlier regions (100k-window+-100k)

1.1 Create a script to run SnpEff

Create VCF files with selected regions & run snpEff

#Create bed files
cv<-c("cov12","cov13","cov23")
#Prevent scientific notation in bed files
options(scipen=999)

#The first line of bed files is often not red by vcftools
for (i in 1:3){
    df<-read.csv(paste0("../Output/COV/COVscan_3pop/3pops_top1percent_outlier_regions.",cv[i],"_new.csv"))
    #select 100k
    df<-df[df$window=="100k",]
    #add 100k
    df$start<-df$start-100000
    df$end<-df$end+100000
    dfp<-df[df$pop=="PWS",1:3]
    colnames(dfp)<-c('track type=bedGraph', '1','1')
    write.table(dfp, paste0("../Output/COV/COVscan_3pop/PWS_outliers_",cv[i],"_new.bed"),quote = F, row.names = F, col.names = T,sep = "\t")
    dft<-df[df$pop=="TB",1:3]
    colnames(dft)<-c('track type=bedGraph', '1','1')
    write.table(dft, paste0("../Output/COV/COVscan_3pop/TB_outliers_",cv[i],"_new.bed"),quote = F, row.names = F, col.names = F,sep = "\t")
    
    if (i==3){
        dfs<-df[df$pop=="SS",1:3]
        colnames(dfs)<-c('track type=bedGraph', '1','1')
        write.table(dfs, paste0("../Output/COV/COVscan_3pop/SS_outliers_",cv[i],"_new.bed"),quote = F, row.names = F, col.names = F,sep = "\t")
    }
}

#for 50k and 75k in PWS
for (i in 1:3){
    df<-read.csv(paste0("../Output/COV/COVscan_3pop/3pops_top1percent_outlier_regions.",cv[i],"_new.csv"))
    df<-df[df$pop=="PWS",]
    df$start<-df$start-100000
    df$end<-df$end+100000
    df50<-df[df$window=="50k",1:3]
    df75<-df[df$window=="75k",1:3]
    colnames(df50)<-c('track type=bedGraph', '1','1')
    colnames(df75)<-c('track type=bedGraph', '1','1')
    
    write.table(df50, paste0("../Output/COV/COVscan_3pop/PWS_outliers_",cv[i],"_50k.bed"),quote = F, row.names = F, col.names = T,sep = "\t")
    write.table(df75, paste0("../Output/COV/COVscan_3pop/PWS_outliers_",cv[i],"_75k.bed"),quote = F, row.names = F, col.names = T,sep = "\t")
}

# Create a bash script to run snpEff
bedfiles<-list.files("../Output/COV/COVscan_3pop/", pattern="*_new.bed")

sink("../COVscan_createVCFs_3Pops2.sh")
cat("#!/bin/bash \n\n")
for (i in 1:length(bedfiles)){
    fname<-gsub(".bed",'', bedfiles[i])
    cat(paste0("vcftools --gzvcf Data/new_vcf/3pop/3pops.MD7000_NS0.5_maf05.vcf.gz --bed Output/COV/COVscan_3pop/", bedfiles[i], " --out Output/COV/COVscan_3pop/", fname," --recode --keep-INFO-all \n"))
}
sink(NULL)  

#create a bash script to run snpEff
vfiles<-list.files("../Output/COV/COVscan_3pop/", pattern=".recode.vcf")

sink("~/programs/snpEff/runsnpEff_cov_3pop.sh")
cat("#!/bin/bash \n\n")
for (i in 1:length(vfiles)){
    fname<-gsub("_new.recode.vcf","",vfiles[i])
    cat(paste0("java -Xmx8g -jar snpEff.jar Ch_v2.0.2.99 ~/Projects/PacHerring/Output/COV/COVscan_3pop/",vfiles[i], " -stats ~/Projects/PacHerring/Output/COV/COVscan_3pop/",fname,".html >  ~/Projects/PacHerring/Output/COV/COVscan_3pop/Anno.",fname,".vcf \n"))
    
    #extract the annotation information
    cat(paste0("bcftools query -f '%CHROM %POS %INFO/AF %INFO/ANN\\n' ~/Projects/PacHerring/Output/COV/COVscan_3pop/Anno.",fname,".vcf > ~/Projects/PacHerring/Output/COV/COVscan_3pop/",fname,"_annotation \n\n"))

}
sink(NULL)  

1.2 Create summary gene files from snpEff and check overlapping genes.

## Create summary files of snpEff results (gene annotations in the regions of interest) and reformat as a ShinyGo input 

#create gene list for ShinyGo
gfiles<-list.files("../Output/COV/COVscan_3pop/", pattern="genes.txt")

for (i in 1:length(gfiles)){
    df<-read.table(paste0("../Output/COV/COVscan_3pop/",gfiles[i]), sep="\t")
    df<-df[,1:7]
    colnames(df)<-c("GeneName","GeneId","TranscriptId","BioType","variants_impact_HIGH","variants_impact_LOW",  "variants_impact_MODERATE")
    
    fname<-gsub(".genes.txt","",gfiles[i])
    genes<-unique(df$GeneId)
    sink(paste0("../Output/COV/COVscan_3pop/geneIDlist_",fname,".txt"))
    cat(paste0(genes,"; "))
    sink(NULL)
}

#Annotation infor from SnpEff
for (c in 1:3){
    if (c!=3){
    for (p in 1:2){
        ano<-read.table(paste0("../Output/COV/COVscan_3pop/",pops[p],"_outliers_",cv[c],"_annotation"), header = F)
        annotations<-data.frame()
        for (i in 1: nrow(ano)){
            anns<-unlist(strsplit(ano$V4[i], "\\,|\\|"))
            annm<-data.frame(matrix(anns,ncol = 16, byrow = TRUE))
            annm<-annm[,c(2,3,4,5,8)]
            colnames(annm)<-c("Effect","Putative_impact","Gene_name","Gene_ID","Feature type")
            annm<-annm[!duplicated(annm), ]
            annm$chr<-ano$V1[i]
            annm$chr<-ano$V1[i]
            annm$pos<-ano$V2[i]
            annm$AF<- ano$V3[i]
            annotations<-rbind(annotations, annm)
        }     
        annotations<-annotations[,c(6:8,1:5)]
        annotations<-annotations[!duplicated(annotations[,1:2]),]
        write.csv(annotations, paste0("../Output/COV/COVscan_3pop/Genes_",pops[p],"_outliers_100k_",cv[c],".csv"), row.names = F)
    }
    }
    if (c==3){
        for (p in 1:3){
        ano<-read.table(paste0("../Output/COV/COVscan_3pop/",pops[p],"_outliers_",cv[c],"_annotation"), header = F)
        annotations<-data.frame()
        for (i in 1: nrow(ano)){
            anns<-unlist(strsplit(ano$V4[i], "\\,|\\|"))
            annm<-data.frame(matrix(anns,ncol = 16, byrow = TRUE))
            annm<-annm[,c(2,3,4,5,8)]
            colnames(annm)<-c("Effect","Putative_impact","Gene_name","Gene_ID","Feature type")
            annm<-annm[!duplicated(annm), ]
            annm$chr<-ano$V1[i]
            annm$chr<-ano$V1[i]
            annm$pos<-ano$V2[i]
            annm$AF<- ano$V3[i]
            annotations<-rbind(annotations, annm)
        }     
        annotations<-annotations[,c(6:8,1:5)]
        annotations<-annotations[!duplicated(annotations[,1:2]),]
        write.csv(annotations, paste0("../Output/COV/COVscan_3pop/Genes_",pops[p],"_outliers_100k_",cv[c],".csv"), row.names = F)
    }
}
  
}

1.3 Find the intersecting gene names across time points within a population

# Find the intersecting gene names across time points
gfiles2<-list.files("../Output/COV/COVscan_3pop/", pattern="geneIDlist")
glist<-list()
for (i in 1:length(gfiles)){
    df<-read.table(paste0("../Output/COV/COVscan_3pop/",gfiles2[i]), sep=";")
    df<-t(df)
    df<-gsub(" ","",df)
    df2<-df[!is.na(df)]
    vname<-gsub(".txt","",gfiles2[i],)
    vname<-gsub("geneIDlist_","", vname)
    glist[[i]]<-df2
    names(glist)[i]<-vname
}

times<-c("cov12","cov13","cov23")
common<-list()
common_genes<-data.frame(time=times)
for (i in 1:3){
    tlist<-glist[grep(times[i], names(glist))]
    if (i !=3){
        common[[i]]<-intersect(tlist[[1]], tlist[[2]])
        names(common)[[i]]<-times[i]
        common_genes$PWS[i]<-length(tlist[[grep("PWS", names(tlist))]])
        common_genes$TB[i]<-length(tlist[[grep("TB", names(tlist))]])
        common_genes$SS[i]<-NA
        common_genes$common_PWS.TB[i]<-length(intersect(tlist[[1]], tlist[[2]]))
    }
    if (i==3){
        common_genes$PWS[i]<-length(tlist[[grep("PWS", names(tlist))]])
        common_genes$TB[i]<-length(tlist[[grep("TB", names(tlist))]])
        common_genes$SS[i]<-length(tlist[[grep("SS", names(tlist))]])
        common_genes$common_PWS.TB[i]<-length(intersect(tlist[[1]], tlist[[3]]))
        common_genes$common_PWS.SS[i]<-length(intersect(tlist[[1]], tlist[[2]]))
        common_genes$common_SS.TB[i]<-length(intersect(tlist[[2]], tlist[[3]]))
        common_genes$common3[i]<-length(intersect(tlist[[1]],intersect(tlist[[2]], tlist[[3]])))
        k=i
        common[[k]]<-intersect(tlist[[1]], tlist[[2]])
        names(common)[[k]]<-paste0(times[i],"_PWS.SS")
        k=k+1
        common[[k]]<-intersect(tlist[[1]], tlist[[3]])
        names(common)[[k]]<-paste0(times[i],"_PWS.TB")
        k=k+1
        common[[k]]<-intersect(tlist[[2]], tlist[[3]])
        names(common)[[k]]<-paste0(times[i],"_SS.TB")
        k=k+1
        common[[k]]<-intersect(tlist[[1]],intersect(tlist[[2]], tlist[[3]]))
        names(common)[[k]]<-paste0(times[i],"_3pops")
        }
}
    
write.csv(common_genes, "../Output/COV/COVscan_3pop/Common_genes_3pops.csv")


#What are the overlapping gene names
#aggregate all gene names
Genes<-data.frame()
for (i in 1:length(gfiles)){
    df<-read.table(paste0("../Output/COV/COVscan_3pop/",gfiles[i]), sep="\t")
    df<-df[,1:2]
    colnames(df)<-c("GeneName","GeneId")
    df<-df[!duplicated(df),]
    Genes<-rbind(Genes, df)
    Genes<-Genes[!duplicated(Genes),]
}

for (i in 1: length(common)){
    gids<-common[[i]]
    df<-data.frame(GeneId=gids)
    
    df<-merge(df, Genes, by="GeneId")
    write.csv(df, paste0("../Output/COV/COVscan_3pop/Common_genes_", names(common)[i],".csv"), row.names = F)
}

1.3.0.1 Overlapping gene numbers

## Check chromosome overlap

2 Compare results from PH_MD7000 (all pops together) and 3Pops-NS0.5 (filter for 3 pops) VCF files

pws1<-read.csv("../Output/COV/COVscan_3pop/3pops_top1percent_outlier_regions.cov12_new.csv")
pws1<-pws1[pws1$pop=="PWS" & pws1$window=="100k",]
pws2<-read.csv("../Output/COV/3pops_top1percent_outlier_regions.cov12.csv")
pws2<-pws2[pws2$pop=="PWS"&pws2$window=="100k",]

pws1$vcf<-"3Pops"
pws2$vcf<-"PH"
pws<-rbind(pws1[,c("chrom","start","end","cov12","vcf")],pws2[,c("chrom","start","end","cov12","vcf")])
pws$chrom<-factor(pws$chrom, levels=paste0("chr", 1:26))
ggplot(data=pws,aes(x=start/1000000, y=cov12, color=vcf, fill=vcf))+
    facet_wrap(~chrom)+
    geom_point(position=position_dodge(width = 0.7), alpha=0.5)+xlab("Position (Mb)")+
    ggtitle("PWS COV12")
ggsave("../Output/COV/COVscan_3pop/PWS_PH.vs.3Pops_outlier_overlap_cov12.png", width = 10, height = 8, dpi=300)

pws1<-read.csv("../Output/COV/COVscan_3pop/3pops_top1percent_outlier_regions.cov23_new.csv")
pws1<-pws1[pws1$pop=="PWS" & pws1$window=="100k",]
pws2<-read.csv("../Output/COV/3pops_top1percent_outlier_regions.cov23.csv")
pws2<-pws2[pws2$pop=="PWS"&pws2$window=="100k",]

pws1$vcf<-"PH"
pws2$vcf<-"3Pops"
pws<-rbind(pws1[,c("chrom","start","end","cov23","vcf")],pws2[,c("chrom","start","end","cov23","vcf")])
pws$chrom<-factor(pws$chrom, levels=paste0("chr", 1:26))
ggplot(data=pws,aes(x=start/1000000, y=cov23, color=vcf, fill=vcf))+
    facet_wrap(~chrom)+
    geom_point(position=position_dodge(width = 0.7), alpha=0.5)+xlab("Position (Mb)")+
    ggtitle("PWS COV23")
ggsave("../Output/COV/COVscan_3pop/PWS_PH.vs.3Pops_outlier_overlap_cov23.png", width = 10, height = 8, dpi=300)

pws1<-read.csv("../Output/COV/COVscan_3pop/3pops_top1percent_outlier_regions.cov13_new.csv")
pws1<-pws1[pws1$pop=="PWS" & pws1$window=="100k",]
pws2<-read.csv("../Output/COV/3pops_top1percent_outlier_regions.cov13.csv")
pws2<-pws2[pws2$pop=="PWS"&pws2$window=="100k",]

pws1$vcf<-"PH"
pws2$vcf<-"3Pops"
pws<-rbind(pws1[,c("chrom","start","end","cov13","vcf")],pws2[,c("chrom","start","end","cov13","vcf")])
pws$chrom<-factor(pws$chrom, levels=paste0("chr", 1:26))
ggplot(data=pws,aes(x=start/1000000, y=cov13, color=vcf, fill=vcf))+
    facet_wrap(~chrom)+
    geom_point(position=position_dodge(width = 0.7), alpha=0.5)+xlab("Position (Mb)")+
    ggtitle("PWS COV13")
ggsave("../Output/COV/COVscan_3pop/PWS_PH.vs.3Pops_outlier_overlap_cov13.png", width = 10, height = 8, dpi=300)

3 Interpopulation comparison per time period

### Interpopulation comparisons
#decode the samples to create the right matrix
cv<-read.csv("~/Projects/Pacherring_Vincent/MD7000/GW_Covs_interPopulations_100k_3pops.csv", header = F)
labs<-read.csv("~/Projects/Pacherring_Vincent/MD7000/GW_Covs_interPopulations_100k_labels_3pops.csv" )
labs<-labs[,-1]
cvm<-data.frame(label=as.vector(t(labs)), cov=as.vector(t(cv)))

#rearrange based on comparions: covariance between populations within the same period
#PopYr Symbols
# PH 1 'PWS', 1991
# PH 2 'PWS', 1996
# PH 3 'PWS', 2006
# PH 4 'PWS', 2017
# PH 5 'SS',  1991
# PH 6 'SS',  1996
# PH 7 'SS',  2006
# PH 8 'SS',  2017
# PH 9 'TB',  1991
# PH 10'TB',  1996
# PH 11'TB',  2006
# PH 12'TB',  2017

Covs<-data.frame(pops=rep(c("PWS.vs.SS", "PWS.vs.TB",  "SS.vs.TB"), times=6),
                 period=c(rep("1991-1996", times=3),rep("1996-2006", times=3), rep("2006-2017", times=3)))

Covs$cov<-c(NA, cvm$cov[cvm$label=="cov(PH: 2-1, PH: 10-9)"],NA,
            cvm$cov[cvm$label=="cov(PH: 3-2, PH: 7-6)"],cvm$cov[cvm$label=="cov(PH: 3-2, PH: 11-10)"], 
            cvm$cov[cvm$label=="cov(PH: 7-6, PH: 11-10)"],
            cvm$cov[cvm$label=="cov(PH: 4-3, PH: 8-7)"],cvm$cov[cvm$label=="cov(PH: 4-3, PH: 12-11)"],cvm$cov[cvm$label=="cov(PH: 8-7, PH: 12-11)"])


#C.I.
cis<-read.csv("~/Projects/Pacherring_Vincent/MD7000/GW_COV_Interpop_comparison_CIs.csv")
cis<-cis[,-1]
cim<-data.frame(label=as.vector(t(labs)), ci_l=as.vector(t(cis[1:11,])))
cim$ci_h<-as.vector(t(cis[12:22,]))

Covs$ci_l<-as.numeric(c(NA,cim$ci_l[cim$label=="cov(PH: 2-1, PH: 10-9)"],NA,
                      cim$ci_l[cim$label=="cov(PH: 3-2, PH: 7-6)"],cim$ci_l[cim$label=="cov(PH: 3-2, PH: 11-10)"], cim$ci_l[cim$label=="cov(PH: 7-6, PH: 11-10)"],
                      cim$ci_l[cim$label=="cov(PH: 4-3, PH: 8-7)"],cim$ci_l[cim$label=="cov(PH: 4-3, PH: 12-11)"], cim$ci_l[cim$label=="cov(PH: 8-7, PH: 12-11)"]))

Covs$ci_h<-as.numeric(c(NA, cim$ci_h[cim$label=="cov(PH: 2-1, PH: 10-9)"],NA,
                      cim$ci_h[cim$label=="cov(PH: 3-2, PH: 7-6)"],cim$ci_h[cim$label=="cov(PH: 3-2, PH: 11-10)"], cim$ci_h[cim$label=="cov(PH: 7-6, PH: 11-10)"],
                      cim$ci_h[cim$label=="cov(PH: 4-3, PH: 8-7)"],cim$ci_h[cim$label=="cov(PH: 4-3, PH: 12-11)"], cim$ci_h[cim$label=="cov(PH: 8-7, PH: 12-11)"]))

#Barplot
ggplot(Covs, aes(x=period, y=cov, fill=pops))+
    geom_bar(stat="identity",position=position_dodge(width = 0.7), width=0.8)+
    ylab("Covariance")+xlab('')+theme_classic()+
    geom_hline(yintercept = 0,color="gray70", size=0.3)+
    scale_fill_manual(values=cols[c(2,1,3)])+
    theme(legend.title = element_blank())+
    scale_y_continuous(labels = comma)+
    ylim(-0.0013, 0.002)+
    geom_errorbar(aes(ymin=ci_l, ymax=ci_h), width=.2, size=.2, position=position_dodge(width = 0.7))
ggsave("../Output/COV/Interpop_cov_comparison_3Pops_new.png",width = 4.7, height = 3, dpi=300)

#Point plot
ggplot(Covs, aes(x=period, y=cov, color=pops))+
    geom_point(position=position_dodge(width = 0.7), size=4)+
    ylab("Covariance")+xlab('')+theme_classic()+
    geom_hline(yintercept = 0,color="gray70", size=0.3)+
    scale_color_manual(values=cols[c(2,1,3)])+
    theme(legend.title = element_blank())+
    scale_y_continuous(labels = comma)+
    geom_errorbar(aes(ymin=ci_l, ymax=ci_h), width=.2, size=.2, position=position_dodge(width = 0.7))+
    ylim(-0.0013, 0.002)+
     geom_vline(xintercept = c(1.5,2.5), color="gray", size=0.3)
ggsave("../Output/COV/Interpop_cov_comparison_3Pops_new_PointPlot.png",width = 4.7, height = 3, dpi=300)

#line plot
Covs$time<-1
Covs$time[Covs$period=="1996-2006"]<-2
Covs$time[Covs$period=="2006-2017"]<-3
Covs<-Covs[order(Covs$time),]
ggplot(Covs, aes(x=time, y=cov, color=pops, group=pops))+
    geom_point(position=position_dodge(width = 0.7), size=4)+
    geom_path(position=position_dodge(width = 0.7))+
    ylab("Covariance")+xlab('')+theme_classic()+
    geom_hline(yintercept = 0,color="gray70", size=0.3)+
    scale_color_manual(values=cols[c(2,1,3)])+
    theme(legend.title = element_blank())+
    scale_y_continuous(labels = comma)+
    geom_errorbar(aes(ymin=ci_l, ymax=ci_h), width=.2, size=.2, position=position_dodge(width = 0.7))+
    ylim(-0.0013, 0.002)+
     geom_vline(xintercept = c(1.5,2.5), color="gray", size=0.3)+
    scale_x_continuous(breaks=c(1,2,3), labels = c("1991-1996","1996-2006","2006-2017"))
ggsave("../Output/COV/Interpop_cov_comparison_3Pops_new_LinePlot.png",width = 4.7, height = 3, dpi=300)

3.1 Longer time period

## Longer time-period
Covs2<-data.frame(pops=rep(c("PWS.vs.SS", "PWS.vs.TB",  "SS.vs.TB"), times=3),
                 period=c(rep("1991-2006", times=3),rep("1991-2017", times=3),rep("1996-2017", times=3)))

cv1<-read.csv("~/Projects/Pacherring_Vincent/MD7000/GW_Covs_interPopulations_100k_1991-2006.csv", header = F)
labs1<-read.csv("~/Projects/Pacherring_Vincent/MD7000/GW_Covs_interPopulations_100k_labels_1991-2006.csv" )
labs1<-labs1[,-1]
cvm1<-data.frame(label=as.vector(t(labs1)), cov=as.vector(t(cv1)))

cv2<-read.csv("~/Projects/Pacherring_Vincent/MD7000/GW_Covs_interPopulations_100k_1991-2017.csv", header = F)
labs2<-read.csv("~/Projects/Pacherring_Vincent/MD7000/GW_Covs_interPopulations_100k_labels_1991-2017.csv" )
labs2<-labs2[,-1]
cvm2<-data.frame(label=as.vector(t(labs2)), cov=as.vector(t(cv2)))

cv3<-read.csv("~/Projects/Pacherring_Vincent/MD7000/GW_Covs_interPopulations_100k_1996-2017.csv", header = F)
labs3<-read.csv("~/Projects/Pacherring_Vincent/MD7000/GW_Covs_interPopulations_100k_labels_1996-2017.csv" )
labs3<-labs3[,-1]
cvm3<-data.frame(label=as.vector(t(labs3)), cov=as.vector(t(cv3)))

Covs2$cov<-c(NA, cvm1$cov[cvm1$label=="cov(PH: 2-1, PH: 4-3)"], NA,
             NA, cvm2$cov[cvm2$label=="cov(PH: 2-1, PH: 4-3)"], NA,
             cvm3$cov[cvm3$label=="cov(PH: 2-1, PH: 4-3)"], cvm3$cov[cvm3$label=="cov(PH: 2-1, PH: 6-5)"], cvm3$cov[cvm3$label=="cov(PH: 4-3, PH: 6-5)"])

#C.I.
cis1<-read.csv("~/Projects/Pacherring_Vincent/MD7000/GW_COV_Interpop_comparison_CIs_1991-2006.csv")
cis1<-cis1[,-1]
cis2<-read.csv("~/Projects/Pacherring_Vincent/MD7000/GW_COV_Interpop_comparison_CIs_1991-2017.csv")
cis2<-cis2[,-1]
cis3<-read.csv("~/Projects/Pacherring_Vincent/MD7000/GW_COV_Interpop_comparison_CIs_1996-2017.csv")
cis3<-cis3[,-1]

#cim<-data.frame(label=as.vector(t(labs)), ci_l=as.vector(t(cis1[1:4,])))
#cim$ci_h<-as.vector(t(cis[12:22,]))

Covs2$ci_l<-as.numeric(c(NA,cis1[1,3],NA,
                        NA,cis2[1,3],NA,
                      cis3[1,3],cis3[1,5],cis3[3,5]))

Covs2$ci_h<-as.numeric(c(NA,cis1[4,3],NA,
                        NA,cis2[4,3],NA,
                      cis3[6,3],cis3[6,5],cis3[8,5]))


ggplot(Covs2, aes(x=period, y=cov, fill=pops))+
    geom_bar(stat="identity",position=position_dodge(width = 0.7), width=0.8)+
    ylab("Covariance")+xlab('')+theme_classic()+
    geom_hline(yintercept = 0,color="gray70", size=0.3)+
    scale_fill_manual(values=cols[c(2,1,3)])+
    theme(legend.title = element_blank())+scale_y_continuous(labels = comma)+
    ylim(-0.0013, 0.002)+
    geom_errorbar(aes(ymin=ci_l, ymax=ci_h), width=.2, size=.2, position=position_dodge(width = 0.7))
ggsave("../Output/COV/Interpop_cov_comparison_3Pops_LonogerPeriod.png",width = 4.7, height = 3, dpi=300)

ggplot(Covs2, aes(x=period, y=cov, color=pops))+
    geom_point(position=position_dodge(width = 0.7), size=4)+
    ylab("Covariance")+xlab('')+theme_classic()+
    geom_hline(yintercept = 0,color="gray70", size=0.3)+
    scale_color_manual(values=cols[c(2,1,3)])+
    theme(legend.title = element_blank())+
    scale_y_continuous(labels = comma)+
     ylim(-0.0013, 0.002)+
    geom_errorbar(aes(ymin=ci_l, ymax=ci_h), width=.2, size=.2, position=position_dodge(width = 0.7))+
    geom_vline(xintercept = c(1.5,2.5), color="gray", size=0.3)
ggsave("../Output/COV/Interpop_cov_comparison_3PopsLonogerPeriod_PointPlot.png",width = 4.7, height = 3, dpi=300)

4 Focused freq analysis

4.1 rel gene (chr13: 23070000 - 23080000)

pops<-c("PWS91","PWS96","PWS07","PWS17")
yr<-c(1991,1996,2007,2017)
maf<-data.frame()
for (i in 1:4){
    af<-read.table(paste0("../Data/new_vcf/AF/",pops[i],".mafs"),sep="\t", header = T)
    af<-af[af$chromo=="chr13"&af$position>=23070000&af$position<=23080000,]
    af$year<-yr[i]
    maf<-rbind(maf,af)
}
#write.csv(maf,"../Output/COV/COVscan_3pop/AF_maf_chr13_23Mb.csv")

ggplot(maf, aes(x=year, y=knownEM, color=factor(position)))+
    geom_point()+
    geom_path()+ggtitle("MAF (ANGSD)")+
    ylab("maf")+
    theme(legend.title=element_blank())
ggsave("../Output/COV/COVscan/AF_ch13_23.07-23.08_angsd.png", width = 5, height=3, dpi=300)


AF<-data.frame()
for (i in 1:4){
    af<-read.table(paste0("../Data/new_vcf/AF/",pops[i],"_maf05_af.frq"),header = FALSE, skip=1, col.names = c("chr","pos","n_allele","n_sample","MajorAF","MAF"))
    af<-af[af$chr=="chr13"&af$pos>=23070000&af$pos<=23080000,]
    af$year<-yr[i]
    af$maf<-substr(af$MAF, 3,10)
    af$maf<-as.numeric(af$maf)
    af<-af[,c("chr","pos","maf","year")]
    AF<-rbind(AF,af)
}
ggplot(AF, aes(x=year, y=maf, color=factor(pos)))+
    geom_point()+
    geom_path()+ggtitle("MAF (vcftools)")+
    theme(legend.title=element_blank())
ggsave("../Output/COV/COVscan/AF_ch13_23.07-23.08.png", width = 5, height=3, dpi=300)


###TB
pops<-c("TB91","TB96","TB06","TB17","PWS91","PWS96","PWS07","PWS17","SS96","SS06","SS17")
yr<-c(1991,1996,2006,2017,1991,1996,2007,2017,1996,2006,2017)
maf<-data.frame()
for (i in 1:length(pops)){
    af<-read.table(paste0("../Data/new_vcf/AF/",pops[i],".mafs"),sep="\t", header = T)
    af<-af[af$chromo=="chr13"&af$position>=23070000&af$position<=23080000,]
    af$year<-yr[i]
    af$pop<-sub("\\d\\d","", pops[i])
    maf<-rbind(maf,af)
}
#write.csv(maf,"../Output/COV/COVscan_3pop/AF_maf_chr13_23Mb.csv")
ggplot(maf, aes(x=year, y=knownEM, color=pop))+
    facet_wrap(~factor(position))+
    geom_point()+
    geom_path()+ggtitle("Chr13 (rel gene)")+
    ylab("maf")+
    theme(legend.title=element_blank())
ggsave("../Output/COV/COVscan/AF_ch13_23.07-23.08_angsd.png", width = 5, height=3, dpi=300)

LS0tCnRpdGxlOiAiQ09WIHNjYW4gMyBwb3B1bGF0aW9ucyIKb3V0cHV0OgogIGh0bWxfbm90ZWJvb2s6CiAgICAgIHRvYzogdHJ1ZSAKICAgICAgdG9jX2Zsb2F0OiB0cnVlCiAgICAgIG51bWJlcl9zZWN0aW9uczogdHJ1ZQogICAgICB0aGVtZTogbHVtZW4KICAgICAgaGlnaGxpZ2h0OiB0YW5nbwogICAgICBjb2RlX2ZvbGRpbmc6IGhpZGUKICAgICAgZGZfcHJpbnQ6IHBhZ2VkCi0tLQoKYGBge3IgZXZhbD1GQUxTRSwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRSwgaW5jbHVkZT1GQUxTRX0Kc291cmNlKCIuLi9Sc2NyaXB0cy9CYXNlU2NyaXB0cy5SIikKbGlicmFyeSh0aWR5dmVyc2UpCmxpYnJhcnkoZHBseXIpCmxpYnJhcnkoY293cGxvdCkKbGlicmFyeShzY2FsZXMpCmBgYAoKCgoKIyMgUGxvdCB0aGUgY292YXJpYW5jZXMgYWNyb3NzIHRoZSBnZW5vbWUgIAoKYGBge3IgZXZhbD1GQUxTRSwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KCiNGaW5kIHRoZSByZWdpb25zIHdpdGggYSBoaWdoIHRlbXBvcmFsIGNvdmFyaWFuY2UgCnBvcHM8LWMoIlBXUyIsIlRCIiwiU1MiKQp3aW5zaXplPC1jKCI1MGsiLCI3NWsiLCIxMDBrIikKZXZlbnM8LXBhc3RlMCgiY2hyIixzZXEoMiwyNiwgYnk9MikpCmNvdi5saXN0PC1saXN0KCkKY292c19hbGw8LWxpc3QoKQprPTEKZm9yIChwIGluIDE6IGxlbmd0aChwb3BzKSl7CiAgICBwb3A8LXBvcHNbcF0KICAgIGZvciAoaSBpbiAxOiBsZW5ndGgod2luc2l6ZSkpewogICAgICAgIGl2PC1yZWFkLmNzdihwYXN0ZTAoIn4vUHJvamVjdHMvUGFjaGVycmluZ19WaW5jZW50L01ENzAwMC8zcG9wc19pbnRlcnZhbHNfIix3aW5zaXplW2ldLCJ3aW5kb3cuY3N2IiksIHJvdy5uYW1lcyA9IDEpCiAgICAgICAgaWYgKHA9PTMpIHsKICAgICAgICAgICAgY292MjM8LXJlYWQuY3N2KHBhc3RlMCgifi9Qcm9qZWN0cy9QYWNoZXJyaW5nX1ZpbmNlbnQvTUQ3MDAwLyIscG9wLCJfY292MjNfMjAxNy0yMDA2XzIwMDYtMTk5Nl8zUG9wc18iLHdpbnNpemVbaV0sIndpbmRvdy5jc3YiKSwgaGVhZGVyID0gRikKICAgICAgICAgICAgY292czwtY2JpbmQoaXYsIGNvdjIzKQogICAgICAgICAgICBjb2xuYW1lcyhjb3ZzKVs0XTwtYygiY292MjMiKQogICAgICAgICAgICBjb3ZzJGluZGV4PTE6bnJvdyhjb3ZzKQogICAgICAgICAgICBjb3ZzJGNvbG9yPC0iY29sMSIKICAgICAgICAgICAgY292cyRjb2xvcltjb3ZzJGNocm9tICVpbiUgZXZlbnNdPC0iY29sMiIKICAgIAogICAgICAgICAgICBjb3ZzW3NhcHBseShjb3ZzLCBpcy5pbmZpbml0ZSldIDwtIE5BCiAgICAgICAgICAgIGNvdnNbc2FwcGx5KGNvdnMsIGlzLm5hbildIDwtIE5BCiAgICAgICAgICAgIAogICAgICAgICAgICBjb3YubGlzdFtba11dPC1jb3ZzCiAgICAgICAgICAgIG5hbWVzKGNvdi5saXN0KVtrXTwtcGFzdGUwKHBvcCwiXyIsd2luc2l6ZVtpXSkgICAgCiAgICAgICAgICAgIGs9aysxCiAgICAgICAgICAgIAogICAgICAgICAgICB5PC1taW4oY292cyRjb3YyMywgbmEucm09VCkKICAgICAgICAgICAgeW1pbjwtaWZlbHNlICh5PD0tMC4xLC0wLjEsIHkpIAogICAgICAgICAgICB5bWF4PC1tYXgoY292cyRjb3YyMywgbmEucm09VCkKICAgICAgICAgICAgZ2dwbG90KGNvdnMsIGFlcyh4PWluZGV4LCB5PWNvdjIzLCBjb2xvcj1jb2xvcikpKwogICAgICAgICAgICAgICAgZ2VvbV9wb2ludChzaXplPTEsIGFscGhhPTAuNSkrCiAgICAgICAgICAgICAgICB0aGVtZV9jbGFzc2ljKCkrCiAgICAgICAgICAgICAgICB5bGltKHltaW4seW1heCkrCiAgICAgICAgICAgICAgICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzPWMoImdyYXk3MCIsInN0ZWVsYmx1ZSIpLCBndWlkZT0ibm9uZSIpKwogICAgICAgICAgICAgICAgeWxhYigiQ292YXJpYW5jZSIpK3hsYWIoJ0Nocm9tb3NvbWUnKSsKICAgICAgICAgICAgICAgIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF9ibGFuaygpKSsKICAgICAgICAgICAgICAgIGdndGl0bGUocGFzdGUwKHBvcCwiICIsIHdpbnNpemVbaV0sIiB3aW5kb3ciKSkKICAgICAgICAgICAgI2dnc2F2ZShwYXN0ZTAoIi4uL091dHB1dC9DT1YvM1BvcHMuIixwb3AsIl90ZW1wQ292c19hY3Jvc3NHZW5vbWVfIix3aW5zaXplW2ldLCAiV2luZG93LnBuZyIpLCB3aWR0aCA9IDgsIGhlaWdodCA9IDIuNywgZHBpPTMwMCkgCiAgICAgICAgfQogICAgICAgIGVsc2UgewogICAgICAgICAgICBjb3YxMjwtcmVhZC5jc3YocGFzdGUwKCJ+L1Byb2plY3RzL1BhY2hlcnJpbmdfVmluY2VudC9NRDcwMDAvIixwb3AsIl9jb3YxMl8xOTk2LTE5OTFfMjAwNi0xOTk2XzNQb3BzXyIsd2luc2l6ZVtpXSwid2luZG93LmNzdiIpLCBoZWFkZXIgPSBGKQogICAgICAgICAgICBjb3YyMzwtcmVhZC5jc3YocGFzdGUwKCJ+L1Byb2plY3RzL1BhY2hlcnJpbmdfVmluY2VudC9NRDcwMDAvIixwb3AsIl9jb3YyM18yMDE3LTIwMDZfMjAwNi0xOTk2XzNQb3BzXyIsd2luc2l6ZVtpXSwid2luZG93LmNzdiIpLCBoZWFkZXIgPSBGKQogICAgICAgICAgICBjb3YxMzwtcmVhZC5jc3YocGFzdGUwKCJ+L1Byb2plY3RzL1BhY2hlcnJpbmdfVmluY2VudC9NRDcwMDAvIixwb3AsIl9jb3YxM18yMDE3LTIwMDZfMTk5Ni0xOTkxXzNQb3BzXyIsd2luc2l6ZVtpXSwid2luZG93LmNzdiIpLCBoZWFkZXIgPSBGKQogICAgICAgICAgICBjb3ZzPC1jYmluZChpdiwgY292MTIsIGNvdjIzLGNvdjEzKQogICAgICAgICAgICBjb2xuYW1lcyhjb3ZzKVs0OjZdPC1jKCJjb3YxMiIsImNvdjIzIiwiY292MTMiKQogICAgICAgICAgICBjb3ZzJGluZGV4PTE6bnJvdyhjb3ZzKQogICAgCiAgICAgICAgICAgIGNvdnMkY29sb3I8LSJjb2wxIgogICAgICAgICAgICBjb3ZzJGNvbG9yW2NvdnMkY2hyb20gJWluJSBldmVuc108LSJjb2wyIgogICAgCiAgICAgICAgICAgIGNvdnNbc2FwcGx5KGNvdnMsIGlzLmluZmluaXRlKV0gPC0gTkEKICAgICAgICAgICAgY292c1tzYXBwbHkoY292cywgaXMubmFuKV0gPC0gTkEKICAgICAgICAgICAgCiAgICAgICAgICAgIGNvdi5saXN0W1trXV08LWNvdnMKICAgICAgICAgICAgbmFtZXMoY292Lmxpc3QpW2tdPC1wYXN0ZTAocG9wLCJfIix3aW5zaXplW2ldKSAgICAKICAgICAgICAgICAgaz1rKzEKICAgICAgICAgICAgY292c208LW1lbHQoY292c1ssYygiaW5kZXgiLCJjb2xvciIsImNvdjEyIiwiY292MjMiLCJjb3YxMyIpXSwgaWQudmFycyA9IGMoImluZGV4IiwgImNvbG9yIikpCiAgICAgICAgICAgIHltYXg8LW1heChjb3ZzbSR2YWx1ZSwgbmEucm09VCkKICAgICAgICAgICAgeTwtbWluKGNvdnNtJHZhbHVlLCBuYS5ybT1UKQogICAgICAgICAgICB5bWluPC1pZmVsc2UgKHk8PS0wLjEsLTAuMSwgeSkgCiAgICAgICAgICAgIGdncGxvdChjb3ZzbSwgYWVzKHg9aW5kZXgsIHk9dmFsdWUsIGNvbG9yPWNvbG9yKSkrCiAgICAgICAgICAgICAgICBmYWNldF93cmFwKH52YXJpYWJsZSwgbnJvdz0zKSsKICAgICAgICAgICAgICAgIGdlb21fcG9pbnQoc2l6ZT0xLCBhbHBoYT0wLjUpKwogICAgICAgICAgICAgICAgdGhlbWVfY2xhc3NpYygpKwogICAgICAgICAgICAgICAgeWxpbSh5bWluLHltYXgpKwogICAgICAgICAgICAgICAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcz1jKCJncmF5NzAiLCJzdGVlbGJsdWUiKSwgZ3VpZGU9Im5vbmUiKSsKICAgICAgICAgICAgICAgIHlsYWIoIkNvdmFyaWFuY2UiKSt4bGFiKCdDaHJvbW9zb21lJykrCiAgICAgICAgICAgICAgICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfYmxhbmsoKSkrCiAgICAgICAgICAgICAgICBnZ3RpdGxlKHBhc3RlMChwb3AsIiAiLCB3aW5zaXplW2ldLCIgd2luZG93IikpCiAgICAgICAgICAgICNnZ3NhdmUocGFzdGUwKCIuLi9PdXRwdXQvQ09WLzNQb3BzLiIscG9wLCJfdGVtcENvdnNfYWNyb3NzR2Vub21lXyIsd2luc2l6ZVtpXSwgIldpbmRvdy5wbmciKSwgd2lkdGggPSA4LCBoZWlnaHQgPSA4LCBkcGk9MzAwKSAgICAKICAgICAgICB9CiAgICB9Cn0KYGBgCgohW10oLi4vT3V0cHV0L0NPVi8zUG9wcy5QV1NfdGVtcENvdnNfYWNyb3NzR2Vub21lXzEwMGtXaW5kb3cucG5nKXt3aWR0aD02NSV9CgohW10oLi4vT3V0cHV0L0NPVi8zUG9wcy5UQl90ZW1wQ292c19hY3Jvc3NHZW5vbWVfMTAwa1dpbmRvdy5wbmcpe3dpZHRoPTY1JX0gICAKCiFbXSguLi9PdXRwdXQvQ09WLzNQb3BzLlNTX3RlbXBDb3ZzX2Fjcm9zc0dlbm9tZV8xMDBrV2luZG93LnBuZyl7d2lkdGg9NjUlfSAgCiFbXSguLi9PdXRwdXQvQ09WLzNQb3BzLlNTX3RlbXBDb3ZzX2Fjcm9zc0dlbm9tZV83NWtXaW5kb3cucG5nKXt3aWR0aD02NSV9ICAKCiFbXSguLi9PdXRwdXQvQ09WLzNQb3BzLlNTX3RlbXBDb3ZzX2Fjcm9zc0dlbm9tZV81MGtXaW5kb3cucG5nKXt3aWR0aD02NSV9ICAKCgojIyBGaW5kIHRoZSBvdXRsaWVyIHJlZ2lvbnMgZm9yIGVhY2ggdGltZSBwZXJpb2QgIAoKYGBge3IgZXZhbD1GQUxTRSwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KCiNmaW5kIGhvdyBvdXRsaWVycyBvdmVybGFwIGJldHdlZW4gZGlmZmVyZW50IHdpbmRvd3MKY292MTI8LWRhdGEuZnJhbWUoKQpjb3YyMzwtZGF0YS5mcmFtZSgpCmNvdjEzPC1kYXRhLmZyYW1lKCkKCmZvciAoaSBpbiAxOmxlbmd0aChjb3YubGlzdCkpewogaWYgKGdyZXBsKCJQV1MiLG5hbWVzKGNvdi5saXN0KVtpXSl8Z3JlcGwoIlRCIixuYW1lcyhjb3YubGlzdClbaV0pKXsKICAgIGNvdnM8LWNvdi5saXN0W1tpXV0KICAgIAogICAgcG9wPC1nc3ViKCJfLisiLCcnLCBuYW1lcyhjb3YubGlzdClbaV0pCiAgICB3aW48LWdzdWIocGFzdGUwKHBvcCwiXyIpLCAnJywgbmFtZXMoY292Lmxpc3QpW2ldKQogICAgCiAgICBjb3ZzPC1jb3ZzW29yZGVyKGNvdnMkY292MTIsIGRlY3JlYXNpbmc9VCksXQogICAgbjwtY2VpbGluZyhucm93KGNvdnMpKjAuMDEpICN0b3AxJSByZWdpb24KICAgIGNvdnMxMl90b3A8LWNvdnNbMTpuLGMoMTo0KV0KICAgIGNvdnMxMl90b3A8LWNvdnMxMl90b3Bbb3JkZXIoY292czEyX3RvcCRjaHJvbSwgY292czEyX3RvcCRzdGFydCksXQogICAgY292czEyX3RvcCR3aW5kb3c8LXdpbgogICAgY292czEyX3RvcCRwb3A8LXBvcAogICAgY292MTI8LXJiaW5kKGNvdjEyLCBjb3ZzMTJfdG9wKQogICAgCiAgICBjb3ZzPC1jb3ZzW29yZGVyKGNvdnMkY292MTMsIGRlY3JlYXNpbmc9VCksXQogICAgbjwtY2VpbGluZyhucm93KGNvdnMpKjAuMDEpICN0b3AxJSByZWdpb24KICAgIGNvdnMxM190b3A8LWNvdnNbMTpuLGMoMTozLDYpXQogICAgY292czEzX3RvcDwtY292czEzX3RvcFtvcmRlcihjb3ZzMTNfdG9wJGNocm9tLCBjb3ZzMTNfdG9wJHN0YXJ0KSxdCiAgICBjb3ZzMTNfdG9wJHdpbmRvdzwtd2luCiAgICBjb3ZzMTNfdG9wJHBvcDwtcG9wCiAgICBjb3YxMzwtcmJpbmQoY292MTMsIGNvdnMxM190b3ApCiAgICAKICAgIGNvdnM8LWNvdnNbb3JkZXIoY292cyRjb3YyMywgZGVjcmVhc2luZz1UKSxdCiAgICBuPC1jZWlsaW5nKG5yb3coY292cykqMC4wMSkgI3RvcDElIHJlZ2lvbgogICAgY292czIzX3RvcDwtY292c1sxOm4sYygxOjMsNSldCiAgICBjb3ZzMjNfdG9wPC1jb3ZzMjNfdG9wW29yZGVyKGNvdnMyM190b3AkY2hyb20sIGNvdnMyM190b3Akc3RhcnQpLF0KICAgIGNvdnMyM190b3Akd2luZG93PC13aW4KICAgIGNvdnMyM190b3AkcG9wPC1wb3AKICAgIGNvdjIzPC1yYmluZChjb3YyMywgY292czIzX3RvcCkKIH0KIGlmIChncmVwbCgiU1MiLG5hbWVzKGNvdi5saXN0KVtpXSkpewogICAgY292czwtY292Lmxpc3RbW2ldXQogICAgCiAgICBwb3A8LWdzdWIoIl8uKyIsJycsIG5hbWVzKGNvdi5saXN0KVtpXSkKICAgIHdpbjwtZ3N1YihwYXN0ZTAocG9wLCJfIiksICcnLCBuYW1lcyhjb3YubGlzdClbaV0pCiAgICAKICAgIGNvdnM8LWNvdnNbb3JkZXIoY292cyRjb3YyMywgZGVjcmVhc2luZz1UKSxdCiAgICBuPC1jZWlsaW5nKG5yb3coY292cykqMC4wMSkgI3RvcDElIHJlZ2lvbgogICAgY292czIzX3RvcDwtY292c1sxOm4sYygxOjQpXQogICAgY292czIzX3RvcDwtY292czIzX3RvcFtvcmRlcihjb3ZzMjNfdG9wJGNocm9tLCBjb3ZzMjNfdG9wJHN0YXJ0KSxdCiAgICBjb3ZzMjNfdG9wJHdpbmRvdzwtd2luCiAgICBjb3ZzMjNfdG9wJHBvcDwtcG9wCiAgICBjb3YyMzwtcmJpbmQoY292MjMsIGNvdnMyM190b3ApCiAgICAKICAgIH0KfQoKCndyaXRlLmNzdihjb3YxMiwgIi4uL091dHB1dC9DT1YvM3BvcHNfdG9wMXBlcmNlbnRfb3V0bGllcl9yZWdpb25zLmNvdjEyX25ldy5jc3YiLHJvdy5uYW1lcyA9IEYpCndyaXRlLmNzdihjb3YyMywgIi4uL091dHB1dC9DT1YvM3BvcHNfdG9wMXBlcmNlbnRfb3V0bGllcl9yZWdpb25zLmNvdjIzX25ldy5jc3YiLHJvdy5uYW1lcyA9IEYpCndyaXRlLmNzdihjb3YxMywgIi4uL091dHB1dC9DT1YvM3BvcHNfdG9wMXBlcmNlbnRfb3V0bGllcl9yZWdpb25zLmNvdjEzX25ldy5jc3YiLHJvdy5uYW1lcyA9IEYpCgpgYGAKCgoKYGBge3IgZXZhbD1GQUxTRSwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KI0NyZWF0ZSBwbG90cyB3aXRoIGRpZmZlcmVudCBjb2xvcnMgZm9yIG91dGxpZXJzCiNmb3IgQ09WMTIgYW5kIENPVjEzIGZvciBUQiBhbmQgUFdTICgxMDBLKQpjdjwtYygiY292MTIiLCJjb3YxMyIsImNvdjIzIikKd2luc2l6ZTwtYygiNTBrIiwiNzVrIiwiMTAwayIpCgpmb3IgKGkgaW4gMTpsZW5ndGgoY3YpKXsKICAgIGlmIChpPT0xfGk9PTIpewogICAgICAgIGZvciAodyBpbiAxOiBsZW5ndGgod2luc2l6ZSkpewogICAgICAgICAgICAjUFdTCiAgICAgICAgICAgIGRmMTwtY292Lmxpc3RbW3Bhc3RlMCgiUFdTXyIsIHdpbnNpemVbd10pXV0KICAgICAgICAgICAgZGYxPC1kZjFbb3JkZXIoZGYxWyxjdltpXV0sIGRlY3JlYXNpbmc9VCksXQogICAgICAgICAgICBuPC1jZWlsaW5nKG5yb3coZGYxKSowLjAxKSAjdG9wMSUgcmVnaW9uCiAgICAgICAgICAgIGRmMSR0b3AxPC0iTiIKICAgICAgICAgICAgZGYxJHRvcDFbMTpuXTwtIlBXUyIKICAgICAgICAgICAgCiAgICAgICAgICAgICN0YgogICAgICAgICAgICBkZjI8LWNvdi5saXN0W1twYXN0ZTAoIlRCXyIsIHdpbnNpemVbd10pXV0KICAgICAgICAgICAgZGYyPC1kZjJbb3JkZXIoZGYyWyxjdltpXV0sIGRlY3JlYXNpbmc9VCksXQogICAgICAgICAgICBkZjIkdG9wMTwtIk4iCiAgICAgICAgICAgIGRmMiR0b3AxWzE6bl08LSJUQiIKICAgICAgICAgICAgCiAgICAgICAgICAgIGNvPC1yYmluZChkZjEsIGRmMikKICAgIAogICAgICAgICAgICBjbyRjaHJvbTwtZmFjdG9yKGNvJGNocm9tLCBsZXZlbHM9cGFzdGUwKCJjaHIiLCAxOjI2KSkKICAgICAgICAgICAgY28kdG9wMTwtZmFjdG9yKGNvJHRvcDEsIGxldmVscz1jKCJQV1MiLCJUQiIsIk4iKSkKICAgICAgICAgICAgY29sbmFtZXMoY28pW3doaWNoKGNvbG5hbWVzKGNvKT09Y3ZbaV0pXTwtImNvdiIKICAgIAogICAgICAgICAgICB5bWF4PC1tYXgoY28kY292LCBuYS5ybT1UKQogICAgICAgICAgICBnZ3Bsb3QoY28sIGFlcyh4PXN0YXJ0LzEwMDAwMDAsIHk9Y292LCBjb2xvcj10b3AxKSkrCiAgICAgICAgICAgICAgICBnZW9tX3BvaW50KHNpemU9MC41KSsKICAgICAgICAgICAgICAgIGZhY2V0X3dyYXAofmNocm9tLCBuY29sPTQpKwogICAgICAgICAgICAgICAgdGhlbWVfY2xhc3NpYygpK3lsaW0oLTAuMSx5bWF4KSsKICAgICAgICAgICAgICAgIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXM9YygiZGVlcHBpbmsiLCJvcmFuZ2UiICwiI0FERDhFNjgwIiksIGxhYmVscz1jKCJQV1MiLCAiVEIiLCAiIikpKwogICAgICAgICAgICAgICAgeWxhYigiQ292YXJpYW5jZSIpK3hsYWIoJ1Bvc3Rpb24gKE1iKScpKwogICAgICAgICAgICAgICAgZ2d0aXRsZShwYXN0ZTAod2luc2l6ZVt3XSwiIHdpbmRvdyAiLGN2W2ldKSkrCiAgICAgICAgICAgICAgICBzY2FsZV94X2NvbnRpbnVvdXMobGFiZWxzID0gY29tbWEpKwogICAgICAgICAgICAgICAgZ3VpZGVzKGNvbG9yID0gZ3VpZGVfbGVnZW5kKG92ZXJyaWRlLmFlcyA9IGxpc3QoY29sb3I9YygiZGVlcHBpbmsiLCJvcmFuZ2UiLCJ3aGl0ZSIpKSwgdGl0bGU9ZWxlbWVudF90ZXh0KCJUb3AgMSUiKSkpCiAgIAogICAgICAgICAgICAgICAgZ2dzYXZlKHBhc3RlMCgiLi4vT3V0cHV0L0NPVi9DT1ZzY2FuXzNwb3AvM1BvcHMuIixjdltpXSwiX3BlckNocm9tXyIsd2luc2l6ZVt3XSwgIldpbmRvd19PdXRsaWVycy5wbmciKSwgd2lkdGggPSAxMCwgaGVpZ2h0ID0gOCwgZHBpPTMwMCkKICAgICAgICB9CiAgICAgICAKICAgIH0KICAgCiAgICBpZiAoaT09Myl7CiAgICAgICAgZm9yICh3IGluIDE6IGxlbmd0aCh3aW5zaXplKSl7CiAgICAgICAgI3B3cwogICAgICAgIGRmMTwtY292Lmxpc3RbW3Bhc3RlMCgiUFdTXyIsIHdpbnNpemVbd10pXV0KICAgICAgICBkZjE8LWRmMVssYygiY2hyb20iLCJzdGFydCIsImVuZCIsImNvdjIzIildCiAgICAgICAgZGYxPC1kZjFbb3JkZXIoZGYxJGNvdjIzLCBkZWNyZWFzaW5nPVQpLF0KICAgICAgICBuPC1jZWlsaW5nKG5yb3coZGYxKSowLjAxKSAjdG9wMSUgcmVnaW9uCiAgICAgICAgZGYxJHRvcDE8LSJOIgogICAgICAgIGRmMSR0b3AxWzE6bl08LSJQV1MiCiAgICAKICAgICAgICAjdGIKICAgICAgICBkZjI8LWNvdi5saXN0W1twYXN0ZTAoIlRCXyIsIHdpbnNpemVbd10pXV0KICAgICAgICBkZjI8LWRmMlssYygiY2hyb20iLCJzdGFydCIsImVuZCIsImNvdjIzIildCiAgICAgICAgZGYyPC1kZjJbb3JkZXIoZGYyJGNvdjIzLCBkZWNyZWFzaW5nPVQpLF0KICAgICAgICBkZjIkdG9wMTwtIk4iCiAgICAgICAgZGYyJHRvcDFbMTpuXTwtIlRCIgogICAgCiAgICAgICAgI3NzCiAgICAgICAgZGYzPC1jb3YubGlzdFtbcGFzdGUwKCJTU18iLCB3aW5zaXplW3ddKV1dCiAgICAgICAgZGYzPC1kZjNbLGMoImNocm9tIiwic3RhcnQiLCJlbmQiLCJjb3YyMyIpXQogICAgICAgIGRmMzwtZGYzW29yZGVyKGRmMyRjb3YyMywgZGVjcmVhc2luZz1UKSxdCiAgICAgICAgZGYzJHRvcDE8LSJOIgogICAgICAgIGRmMyR0b3AxWzE6bl08LSJTUyIKCiAgICAgICAgY288LXJiaW5kKGRmMSxkZjIsZGYzKQoKICAgICAgICBjbyRjaHJvbTwtZmFjdG9yKGNvJGNocm9tLCBsZXZlbHM9cGFzdGUwKCJjaHIiLCAxOjI2KSkKICAgICAgICBjbyR0b3AxPC1mYWN0b3IoY28kdG9wMSwgbGV2ZWxzPWMoIlBXUyIsIlRCIiwiU1MiLCJOIikpCiAgICAgICAgeW1heDwtbWF4KGNvJGNvdjIzLCBuYS5ybT1UKQogICAgICAgIGdncGxvdChjbywgYWVzKHg9c3RhcnQvMTAwMDAwMCwgeT1jb3YyMywgY29sb3I9dG9wMSkpKwogICAgICAgICAgICBnZW9tX3BvaW50KHNpemU9MC41KSsKICAgICAgICAgICAgZmFjZXRfd3JhcCh+Y2hyb20sIG5jb2w9NCkrCiAgICAgICAgICAgIHRoZW1lX2NsYXNzaWMoKSt5bGltKC0wLjEseW1heCkrCiAgICAgICAgICAgIHlsYWIoIkNvdmFyaWFuY2UiKSt4bGFiKCdQb3N0aW9uIChNYiknKSsKICAgICAgICAgICAgZ2d0aXRsZShwYXN0ZTAod2luc2l6ZVt3XSwiIHdpbmRvdyAiLGN2W2ldKSkrCiAgICAgICAgICAgIHNjYWxlX3hfY29udGludW91cyhsYWJlbHMgPSBjb21tYSkrCiAgICAgICAgICAgICNzY2FsZV9jb2xvcl9kaXNjcmV0ZShicmVha3M9YygiUFdTIiwiU1MiLCJUQiIpKSsKICAgICAgICAgICAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcz1jKCJkZWVwcGluayIsIm9yYW5nZSIsZ3JlLCIjQUREOEU2NjYiKSwgbGFiZWxzPWMoIlBXUyIsIlRCIiwiU1MiLCAiIikpKwogICAgICAgICAgICBndWlkZXMoY29sb3IgPSBndWlkZV9sZWdlbmQob3ZlcnJpZGUuYWVzID0gbGlzdChjb2xvcj1jKCJkZWVwcGluayIsIm9yYW5nZSIsZ3JlLCAgICAgICAgICJ3aGl0ZSIpKSx0aXRsZT1lbGVtZW50X3RleHQoIlRvcCAxJSBvdXRsaWVycyIpKSkgCiAgICAgICAgZ2dzYXZlKHBhc3RlMCgiLi4vT3V0cHV0L0NPVi9DT1ZzY2FuXzNwb3AvM1BvcHMuY292MjNfM1BvcHNfcGVyQ2hyb21fIix3aW5zaXplW3ddLCAiV2luZG93X091dGxpZXJzLnBuZyIpLCB3aWR0aCA9IDEwLCBoZWlnaHQgPSA5LCBkcGk9MzAwKQogICAgICAgIH0KICAgIH0KfQpgYGAKCiFbXSguLi9PdXRwdXQvQ09WL0NPVnNjYW5fM3BvcC8zUG9wcy5jb3YxMl9wZXJDaHJvbV8xMDBrV2luZG93X091dGxpZXJzLnBuZykKCiFbXSguLi9PdXRwdXQvQ09WL0NPVnNjYW5fM3BvcC8zUG9wcy5jb3YxMl9wZXJDaHJvbV81MGtXaW5kb3dfT3V0bGllcnMucG5nKSAKIVtdKC4uL091dHB1dC9DT1YvQ09Wc2Nhbl8zcG9wLzNQb3BzLmNvdjEzX3BlckNocm9tXzEwMGtXaW5kb3dfT3V0bGllcnMucG5nKQoKIVtdKC4uL091dHB1dC9DT1YvQ09Wc2Nhbl8zcG9wLzNQb3BzLmNvdjEzX3BlckNocm9tXzUwa1dpbmRvd19PdXRsaWVycy5wbmcpIAoKCiFbXSguLi9PdXRwdXQvQ09WL0NPVnNjYW5fM3BvcC8zUG9wcy5jb3YyM18zUG9wc19wZXJDaHJvbV8xMDBrV2luZG93X091dGxpZXJzLnBuZykgIAohW10oLi4vT3V0cHV0L0NPVi9DT1ZzY2FuXzNwb3AvM1BvcHMuY292MjNfM1BvcHNfcGVyQ2hyb21fNTBrV2luZG93X091dGxpZXJzLnBuZykgIAoKIyMjIFdob2xlIGdlbm9tZSBwbG90cyB3aXRob3V0IGZhY2V0IHdyYXAKCmBgYHtyIGV2YWw9RkFMU0UsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CmN2PC1jKCJjb3YxMiIsImNvdjEzIiwiY292MjMiKQpmb3IgKGkgaW4gMTpsZW5ndGgoY3YpKXsKICAgIGlmIChpPT0xfGk9PTIpewogICAgICAgIGRmMTwtY292Lmxpc3RbWyJQV1NfMTAwayJdXQogICAgICAgIGRmMTwtZGYxW29yZGVyKGRmMVssY3ZbaV1dLCBkZWNyZWFzaW5nPVQpLF0KICAgICAgICBuPC1jZWlsaW5nKG5yb3coZGYxKSowLjAxKSAjdG9wMSUgcmVnaW9uCiAgICAgICAgZGYxJHRvcDE8LSJOIgogICAgICAgIGRmMSR0b3AxWzE6bl08LSJQV1MiCiAgICAgICAgCiAgICAgICAgZGYyPC1jb3YubGlzdFtbIlRCXzEwMGsiXV0KICAgICAgICBkZjI8LWRmMltvcmRlcihkZjJbLGN2W2ldXSwgZGVjcmVhc2luZz1UKSxdCiAgICAgICAgZGYyJHRvcDE8LSJOIgogICAgICAgIGRmMiR0b3AxWzE6bl08LSJUQiIKCiAgICAgICAgY288LXJiaW5kKGRmMSwgZGYyKQogICAgICAgIGNvJGNocm9tPC1mYWN0b3IoY28kY2hyb20sIGxldmVscz1wYXN0ZTAoImNociIsIDE6MjYpKQogICAgICAgIGNvbG5hbWVzKGNvKVt3aGljaChjb2xuYW1lcyhjbyk9PWN2W2ldKV08LSJjb3YiCiAgICAgICAgI2Fzc2dpbiBjb2xvcnMKICAgICAgICBjbyR0b3AxPC1hcHBseShjbywgMSwgZnVuY3Rpb24oeCkge2lmZWxzZSAoeFsndG9wMSddPT0iTiIsIHhbJ2NvbG9yJ10sIHhbJ3RvcDEnXSl9ICkKICAgICAgICBjbyR0b3AxPC1mYWN0b3IoY28kdG9wMSwgbGV2ZWxzPWMoIlBXUyIsIlRCIiwiY29sMSIsImNvbDIiKSkKICAgICAgICAKICAgICAgICAjY291bnQgdGhlIG51bWJlciBvZiBzaXRlcyBwZXIgY2hyb21vc29tZXMKICAgICAgICBwb3NzPC1kYXRhLmZyYW1lKGNocj1wYXN0ZTAoImNociIsMToyNikpCiAgICAgICAgaz0xCiAgICAgICAgZm9yIChqIGluIDE6MjYpewogICAgICAgICAgICBkZjwtZGYxW2RmMSRjaHI9PXBhc3RlMCgiY2hyIixqKSxdCiAgICAgICAgICAgIHBvc3Mkc3RhcnRbal08LWsKICAgICAgICAgICAgcG9zcyRlbmRbal08LWsrbnJvdyhkZiktMQogICAgICAgICAgICBrPWsrbnJvdyhkZikKICAgICAgICB9CiAgICAgICAgcG9zcyR4PC1wb3NzJHN0YXJ0Kyhwb3NzJGVuZC1wb3NzJHN0YXJ0KS8yCiAgICAgICAgeW1heDwtbWF4KGNvJGNvdiwgbmEucm09VCkKICAgICAgICBnZ3Bsb3QoY28sIGFlcyh4PWluZGV4LCB5PWNvdiwgY29sb3I9dG9wMSkpKwogICAgICAgICAgICBnZW9tX3BvaW50KHNpemU9MC41KSsKICAgICAgICAgICAgdGhlbWVfY2xhc3NpYygpK3lsaW0oLTAuMSx5bWF4KSsKICAgICAgICAgICAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcz1jKCIjRkYzMjkzQjMiLCIjMDQzM0ZGQjMiICwiI0FERDhFNjgwIiwiI0MwQzBDMDg4IiksIGxhYmVscz1jKCJQV1MiLCAiVEIiLCAiIiwiIikpKwogICAgICAgICAgICAgICAgeWxhYigiQ292YXJpYW5jZSIpKwogICAgICAgICAgICAgICAgZ2d0aXRsZShwYXN0ZTAoIiAxMDBrIHdpbmRvdyAiLGN2W2ldKSkrCiAgICAgICAgICAgICAgICBndWlkZXMoY29sb3IgPSBndWlkZV9sZWdlbmQob3ZlcnJpZGUuYWVzID0gbGlzdChjb2xvcj1jKCJkZWVwcGluayIsIiMwNDMzRkYiLCJ3aGl0ZSIsIndoaXRlIiksIHNpemU9MiksIHRpdGxlPWVsZW1lbnRfdGV4dCgiT3V0bGllciAoMSUpIiwgc2l6ZT0xMCkpKSsKICAgICAgICAgICAgc2NhbGVfeF9jb250aW51b3VzKG5hbWU9IkNocm9tb3NvbWUiLCBicmVha3M9cG9zcyR4LCBsYWJlbHM9MToyNikKICAgICAgICBnZ3NhdmUocGFzdGUwKCIuLi9PdXRwdXQvQ09WL0NPVnNjYW5fM3BvcC8zUG9wcy4iLGN2W2ldLCJfMTAwa19XaW5kb3dfT3V0bGllcnMucG5nIiksIHdpZHRoID0gMTAsIGhlaWdodCA9IDMuNSwgZHBpPTMwMCkKICAgICAgICB9fQogICAgaWYgKGk9PTMpewogICAgICAgICNwd3MKICAgICAgICBkZjE8LWNvdi5saXN0W1siUFdTXzEwMGsiXV0KICAgICAgICBkZjE8LWRmMVssYygiY2hyb20iLCJzdGFydCIsImVuZCIsImNvdjIzIiwiaW5kZXgiLCJjb2xvciIpXQogICAgICAgIGRmMTwtZGYxW29yZGVyKGRmMSRjb3YyMywgZGVjcmVhc2luZz1UKSxdCiAgICAgICAgbjwtY2VpbGluZyhucm93KGRmMSkqMC4wMSkgI3RvcDElIHJlZ2lvbgogICAgICAgIGRmMSR0b3AxPC1kZjEkY29sb3IKICAgICAgICBkZjEkdG9wMVsxOm5dPC0iUFdTIgogICAgICAgICN0YgogICAgICAgIGRmMjwtY292Lmxpc3RbWyJUQl8xMDBrIl1dCiAgICAgICAgZGYyPC1kZjJbLGMoImNocm9tIiwic3RhcnQiLCJlbmQiLCJjb3YyMyIsImluZGV4IiwiY29sb3IiKV0KICAgICAgICBkZjI8LWRmMltvcmRlcihkZjIkY292MjMsIGRlY3JlYXNpbmc9VCksXQogICAgICAgIGRmMiR0b3AxPC1kZjIkY29sb3IKICAgICAgICBkZjIkdG9wMVsxOm5dPC0iVEIiCiAgICAgICAgI3NzCiAgICAgICAgZGYzPC1jb3YubGlzdFtbIlNTXzEwMGsiXV0KICAgICAgICBkZjM8LWRmM1ssYygiY2hyb20iLCJzdGFydCIsImVuZCIsImNvdjIzIiwiaW5kZXgiLCJjb2xvciIpXQogICAgICAgIGRmMzwtZGYzW29yZGVyKGRmMyRjb3YyMywgZGVjcmVhc2luZz1UKSxdCiAgICAgICAgZGYzJHRvcDE8LWRmMyRjb2xvcgogICAgICAgIGRmMyR0b3AxWzE6bl08LSJTUyIKCiAgICAgICAgY288LXJiaW5kKGRmMSxkZjIsZGYzKQogICAgICAgIGNvJHRvcDE8LWZhY3RvcihjbyR0b3AxLCBsZXZlbHM9YygiUFdTIiwiVEIiLCJTUyIsImNvbDEiLCJjb2wyIikpCiAgICAgICAgCiAgICAgICAgI2NvdW50IHRoZSBudW1iZXIgb2Ygc2l0ZXMgcGVyIGNocm9tb3NvbWVzCiAgICAgICAgcG9zczwtZGF0YS5mcmFtZShjaHI9cGFzdGUwKCJjaHIiLDE6MjYpKQogICAgICAgIGs9MQogICAgICAgIGZvciAoaiBpbiAxOjI2KXsKICAgICAgICAgICAgZGY8LWRmMVtkZjEkY2hyPT1wYXN0ZTAoImNociIsaiksXQogICAgICAgICAgICBwb3NzJHN0YXJ0W2pdPC1rCiAgICAgICAgICAgIHBvc3MkZW5kW2pdPC1rK25yb3coZGYpLTEKICAgICAgICAgICAgaz1rK25yb3coZGYpCiAgICAgICAgfQogICAgICAgIHBvc3MkeDwtcG9zcyRzdGFydCsocG9zcyRlbmQtcG9zcyRzdGFydCkvMgogICAgICAgIHltYXg8LW1heChjbyRjb3YsIG5hLnJtPVQpCiAgICAgICAgZ2dwbG90KGNvLCBhZXMoeD1pbmRleCwgeT1jb3YyMywgY29sb3I9dG9wMSkpKwogICAgICAgICAgICBnZW9tX3BvaW50KHNpemU9MC41KSsKICAgICAgICAgICAgdGhlbWVfY2xhc3NpYygpK3lsaW0oLTAuMSx5bWF4KSsKICAgICAgICAgICAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcz1jKCIjRkYzMjkzQjMiLCIjMDQzM0ZGQjMiLCIjMDA4RjAwQjMiICwiI0FERDhFNjgwIiwiI0MwQzBDMDg4IiksIGxhYmVscz1jKCJQV1MiLCAiVEIiLCJTUyIsICIiLCIiKSkrCiAgICAgICAgICAgICAgICB5bGFiKCJDb3ZhcmlhbmNlIikrCiAgICAgICAgICAgICAgICBnZ3RpdGxlKHBhc3RlMCgiIDEwMGsgd2luZG93ICIsY3ZbaV0pKSsKICAgICAgICAgICAgICAgIGd1aWRlcyhjb2xvciA9IGd1aWRlX2xlZ2VuZChvdmVycmlkZS5hZXMgPSBsaXN0KGNvbG9yPWMoImRlZXBwaW5rIiwiIzA0MzNGRiIsIiMwMDhGMDAiLCJ3aGl0ZSIsIndoaXRlIiksIHNpemU9MiksIHRpdGxlPWVsZW1lbnRfdGV4dCgiT3V0bGllciAoMSUpIikpKSsKICAgICAgICAgICAgc2NhbGVfeF9jb250aW51b3VzKG5hbWU9IkNocm9tb3NvbWUiLCBicmVha3M9cG9zcyR4LCBsYWJlbHM9MToyNikrCiAgICAgICAgICAgIHRoZW1lKGxlZ2VuZC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplPTEwKSkKICAgICAgICBnZ3NhdmUocGFzdGUwKCIuLi9PdXRwdXQvQ09WL0NPVnNjYW5fM3BvcC8zUG9wcy4iLGN2W2ldLCJfMTAwa19XaW5kb3dfT3V0bGllcnMucG5nIiksIHdpZHRoID0gMTAsIGhlaWdodCA9IDMuNSwgZHBpPTMwMCkKICAgICAgICB9CiAgICB9Cn0KCiMjIFBsb3QgMyB0aW1lIHBlcmlvZHMgdG9nZXRoZXIgZm9yIFBXUyBhbmQgVEIKQ292PC1kYXRhLmZyYW1lKCkKZm9yIChpIGluIDE6bGVuZ3RoKGN2KSl7CiAgICBkZjE8LWNvdi5saXN0W1siUFdTXzEwMGsiXV0KICAgIGRmMTwtZGYxW29yZGVyKGRmMVssY3ZbaV1dLCBkZWNyZWFzaW5nPVQpLF0KICAgIG48LWNlaWxpbmcobnJvdyhkZjEpKjAuMDEpICN0b3AxJSByZWdpb24KICAgIGRmMSR0b3AxPC0iTiIKICAgIGRmMSR0b3AxWzE6bl08LSJQV1MiCiAgICAKICAgIGRmMjwtY292Lmxpc3RbWyJUQl8xMDBrIl1dCiAgICBkZjI8LWRmMltvcmRlcihkZjJbLGN2W2ldXSwgZGVjcmVhc2luZz1UKSxdCiAgICBkZjIkdG9wMTwtIk4iCiAgICBkZjIkdG9wMVsxOm5dPC0iVEIiCiAgICBjbzwtcmJpbmQoZGYxLCBkZjIpCiAgICBjbyRjaHJvbTwtZmFjdG9yKGNvJGNocm9tLCBsZXZlbHM9cGFzdGUwKCJjaHIiLCAxOjI2KSkKICAgIGNvbG5hbWVzKGNvKVt3aGljaChjb2xuYW1lcyhjbyk9PWN2W2ldKV08LSJjb3YiCiAgICAjYXNzZ2luIGNvbG9ycwogICAgY28kdG9wMTwtYXBwbHkoY28sIDEsIGZ1bmN0aW9uKHgpIHtpZmVsc2UgKHhbJ3RvcDEnXT09Ik4iLCB4Wydjb2xvciddLCB4Wyd0b3AxJ10pfSApCiAgICBjbyR0b3AxPC1mYWN0b3IoY28kdG9wMSwgbGV2ZWxzPWMoIlBXUyIsIlRCIiwiY29sMSIsImNvbDIiKSkKICAgIGNvJHRpbWU8LWN2W2ldCiAgICAKICAgIENvdjwtcmJpbmQoQ292LCBjb1ssYygiaW5kZXgiLCAiY292IiwidG9wMSIsInRpbWUiKV0pCn0KCiNjb3VudCB0aGUgbnVtYmVyIG9mIHNpdGVzIHBlciBjaHJvbW9zb21lcwpkZjE8LWNvdi5saXN0W1siUFdTXzEwMGsiXV0KcG9zczwtZGF0YS5mcmFtZShjaHI9cGFzdGUwKCJjaHIiLDE6MjYpKQprPTEKZm9yIChqIGluIDE6MjYpewogICAgICAgIGRmPC1kZjFbZGYxJGNocj09cGFzdGUwKCJjaHIiLGopLF0KICAgICAgICBwb3NzJHN0YXJ0W2pdPC1rCiAgICAgICAgcG9zcyRlbmRbal08LWsrbnJvdyhkZiktMQogICAgICAgIGs9aytucm93KGRmKQp9CnBvc3MkeDwtcG9zcyRzdGFydCsocG9zcyRlbmQtcG9zcyRzdGFydCkvMgp5bWF4PC1tYXgoY28kY292LCBuYS5ybT1UKQpnZ3Bsb3QoQ292LCBhZXMoeD1pbmRleCwgeT1jb3YsIGNvbG9yPXRvcDEpKSsKICAgIGZhY2V0X3dyYXAofnRpbWUsIG5jb2w9MSkrCiAgICBnZW9tX3BvaW50KHNpemU9MC41KSsKICAgIHRoZW1lX2NsYXNzaWMoKSt5bGltKC0wLjEseW1heCkrCiAgICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzPWMoIiNGRjMyOTNCMyIsIiMwNDMzRkZCMyIgLCIjQUREOEU2ODAiLCIjQzBDMEMwODgiKSwgbGFiZWxzPWMoIlBXUyIsICJUQiIsICIiLCIiKSkrCiAgICB5bGFiKCJDb3ZhcmlhbmNlIikrCiAgICBndWlkZXMoY29sb3IgPSBndWlkZV9sZWdlbmQob3ZlcnJpZGUuYWVzID0gbGlzdChjb2xvcj1jKCJkZWVwcGluayIsIiMwNDMzRkYiLCJ3aGl0ZSIsIndoaXRlIiksIHNpemU9MiksIHRpdGxlPWVsZW1lbnRfdGV4dCgiT3V0bGllciAoMSUpIiwgc2l6ZT0xMCkpKSsKICAgIHNjYWxlX3hfY29udGludW91cyhuYW1lPSJDaHJvbW9zb21lIiwgYnJlYWtzPXBvc3MkeCwgbGFiZWxzPTE6MjYpCgpnZ3NhdmUocGFzdGUwKCIuLi9PdXRwdXQvQ09WL0NPVnNjYW5fM3BvcC9QV1NfVEJfMTAwa19XaW5kb3dfT3V0bGllcnMucG5nIiksIHdpZHRoID0gMTEsIGhlaWdodCA9IDUsIGRwaT0zMDApCiAgICAgICAgfX0KCgpgYGAKCiFbXSguLi9PdXRwdXQvQ09WL0NPVnNjYW5fM3BvcC9QV1NfVEJfMTAwa19XaW5kb3dfT3V0bGllcnMucG5nKQoKCiMjIE92ZXJsYXBwaW5nIG91dGxpZXIgcmVnaW9ucyBiZXR3ZWVuIGRpZmZlcmVudCB3aW5kb3cgc2l6ZXMgKHRvcDElKSAKYGBge3IgZXZhbD1GQUxTRSwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KIyBIb3cgd2luZG93IHNpemUgYWZmZWN0cyBvdXRsaWVyIHJlZ2lvbnMKCiNDT1YxMgpjdjwtYygiY292MTIiLCJjb3YxMyIsImNvdjIzIikKd2luc2l6ZTwtYygiNTBrIiwiNzVrIiwiMTAwayIpCnBhaXJzPC10KGNvbWJuKHdpbnNpemUsIDIpKQpwYWlyczwtZGF0YS5mcmFtZShwYWlycykKY29sbmFtZXMocGFpcnMpPC1wYXN0ZTAoIndpbmRvdyIsMToyKQpPdjE8LXBhaXJzCk92MjwtcGFpcnMKT3YzPC1wYWlycwojcG9wdWxhdGlvbnM8LWMoIlBXUyIsIlRCIikKZm9yIChpIGluIDE6bGVuZ3RoKGN2KSl7CiAgICBkZjwtcmVhZC5jc3YocGFzdGUwKCIuLi9PdXRwdXQvQ09WLzNwb3BzX3RvcDFwZXJjZW50X291dGxpZXJfcmVnaW9ucy4iLCBjdltpXSwgIl9uZXcuY3N2IikpCiAgICBkZiRpZDwtcGFzdGUwKGRmJGNocm9tLCJfIixkZiRzdGFydCkKICAgIHB3czwtZGZbZGYkcG9wPT0iUFdTIixdCiAgICB0YjwtZGZbZGYkcG9wPT0iVEIiLF0KICAgIGlmIChpPT0zKSBzczwtZGZbZGYkcG9wPT0iU1MiLF0KICAgICAgICAKICAgIGZvcihqIGluIDE6bnJvdyhwYWlycykpewogICAgICAgIGlzZWM8LWludGVyc2VjdChwd3MkaWRbcHdzJHdpbmRvdz09cGFpcnNbaiwxXV0sIHB3cyRpZFtwd3Mkd2luZG93PT1wYWlyc1tqLDJdXSkgCiAgICAgICAgT3YxW2osIGN2W2ldXTwtbGVuZ3RoKGlzZWMpCiAgICAgICAgaXNlYzI8LWludGVyc2VjdCh0YiRpZFt0YiR3aW5kb3c9PXBhaXJzW2osMV1dLCB0YiRpZFt0YiR3aW5kb3c9PXBhaXJzW2osMl1dKSAKICAgICAgICBPdjJbaiwgY3ZbaV1dPC1sZW5ndGgoaXNlYzIpCiAgICAgICAgaWYgKGk9PTMpIHsKICAgICAgICAgICAgICBpc2VjMzwtaW50ZXJzZWN0KHNzJGlkW3NzJHdpbmRvdz09cGFpcnNbaiwxXV0sIHNzJGlkW3NzJHdpbmRvdz09cGFpcnNbaiwyXV0pIAogICAgICAgICAgICAgIE92M1tqLCBjdltpXV08LWxlbmd0aChpc2VjMykKICAgICAgICAgfQogICAgICAgICMjIyMgQ2hlY2sgY2hyb21vc29tZSByZWdpb24gb3ZlcmxhcCArLTIwMCwwMDAgYmFzZXMKICAgICAgICAKICAgICAgICBmb3IocCBpbiAxOmxlbmd0aChwb3BzKSl7CiAgICAgICAgICAgIGlmIChwPT0xKSBkZl9wb3A8LXB3cwogICAgICAgICAgICBpZiAocD09MikgZGZfcG9wPC10YgogICAgICAgICAgICBpZiAocD09MyAmIGV4aXN0cygic3MiKSkge2RmX3BvcDwtc3N9CiAgICAgICAgICAgICAgICBlbHNlIG5leHQKICAgICAgICAKICAgICAgICAgICAgdGltZTE8LWRmX3BvcFtkZl9wb3Akd2luZG93PT1wYWlyc1tqLDFdLF0KICAgICAgICAgICAgdGltZTI8LWRmX3BvcFtkZl9wb3Akd2luZG93PT1wYWlyc1tqLDJdLF0KICAgICAgICAgICAgIAogICAgICAgICAgICBvdmVybHBzPC1kYXRhLmZyYW1lKCkKICAgICAgICAgICAgb3ZlcmxwczI8LWRhdGEuZnJhbWUoKQogICAgICAgIAogICAgICAgICAgICBmb3IgKG4gaW4gMTogbnJvdyh0aW1lMSkpewogICAgICAgICAgICAgICAgcmU8LXRpbWUyW3RpbWUyJGNocm9tPT10aW1lMSRjaHJvbVtuXSxdCiAgICAgICAgICAgICAgICBpZiAobnJvdyhyZSk+PTEpewogICAgICAgICAgICAgICAgICAgIGZvciAocyBpbiAxOiBucm93KHJlKSl7CiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChyZSRzdGFydFtzXTw9dGltZTEkc3RhcnRbbl0rMjAwMDAwICYgcmUkc3RhcnRbc10+PXRpbWUxJHN0YXJ0W25dLTIwMDAwMCl7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBvdmVybHBzPC1yYmluZChvdmVybHBzLCByZVtzLF0pCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBvdmVybHBzMjwtcmJpbmQob3ZlcmxwczIsdGltZTFbbixdKX0KICAgICAgICAgICAgICAgIH19CiAgICAgICAgICAgIH0gICAgICAKICAgICAgICAgICAgI092ZXJsYXBwaW5nIHdpbmRvd3M6CiAgICAgICAgICAgIG92PC1kYXRhLmZyYW1lKGlkPW92ZXJscHMkaWQpCiAgICAgICAgICAgIGZvciAobiBpbiAxOiBucm93KG92ZXJscHMpKXsKICAgICAgICAgICAgICAgIGlmIChvdmVybHBzJHN0YXJ0W25dPG92ZXJscHMyJHN0YXJ0W25dKSB7b3Ykc3RhcnRbbl08LW92ZXJscHMkc3RhcnRbbl07IG92JGVuZFtuXTwtb3ZlcmxwczIkZW5kW25dfQogICAgICAgICAgICAgICAgaWYgKG92ZXJscHMkc3RhcnRbbl0+PW92ZXJscHMyJHN0YXJ0W25dKSB7b3Ykc3RhcnRbbl08LW92ZXJscHMyJHN0YXJ0W25dO292JGVuZFtuXTwtb3ZlcmxwcyRlbmRbbl19CiAgICAgICAgICAgIH0KICAgICAgICAgICAgb3ZbLHBhc3RlMCgiY292LiIscGFpcnNbaiwxXSldPC1vdmVybHBzWyw0XQogICAgICAgICAgICBvdlsscGFzdGUwKCJjb3YuIixwYWlyc1tqLDJdKV08LW92ZXJscHMyWyw0XQogICAgICAgICAgICB3cml0ZS5jc3Yob3YsIHBhc3RlMCgiLi4vT3V0cHV0L0NPVi9DT1ZzY2FuXzNwb3AvT3ZlcmxhcF9yZWdpb25zXyIscG9wc1twXSwiLiIsIHBhaXJzW2osMV0sIi4iLHBhaXJzW2osMl0sICIuIixjdltpXSwgIl9wbHVzbWludXMyMDBrLmNzdiIpLCByb3cubmFtZXMgPSBGKQogICAgICAgIH0KICAgIH0KfQp3cml0ZS5jc3YoT3YxLCBwYXN0ZTAoIi4uL091dHB1dC9DT1YvQ09Wc2Nhbl8zcG9wL092ZXJsYXBwaW5nX3dpbmRvd19jb3VudHNfUFdTLmNzdiIpKQp3cml0ZS5jc3YoT3YyLCBwYXN0ZTAoIi4uL091dHB1dC9DT1YvQ09Wc2Nhbl8zcG9wL092ZXJsYXBwaW5nX3dpbmRvd19jb3VudHNfVEIuY3N2IikpCndyaXRlLmNzdihPdjMsIHBhc3RlMCgiLi4vT3V0cHV0L0NPVi9DT1ZzY2FuXzNwb3AvT3ZlcmxhcHBpbmdfd2luZG93X2NvdW50c19TUy5jc3YiKSkKYGBgCgoKCiMjIE92ZXJsYXBwaW5nIG91dGxpZXIgcmVnaW9ucyBiZXR3ZWVuIGRpZmZlcmVudCBwb3B1bGF0aW9ucyAKYGBge3IgZXZhbD1GQUxTRSwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KIzEwMGsKY3Y8LWMoImNvdjEyIiwiY292MTMiLCJjb3YyMyIpCnBhaXJzPC10KGNvbWJuKHBvcHMsIDIpKQpwYWlyczwtZGF0YS5mcmFtZShwYWlycykKY29sbmFtZXMocGFpcnMpPC1wYXN0ZTAoInBvcCIsMToyKQpPdl9kaXJlY3Q8LWRhdGEuZnJhbWUoY292PWMoY3ZbMToyXSwiY292MjMtUFQiLCJjb3YyMy1QUyIsImNvdjIzLVNUIiAsImNvdjIzLTMiKSkKT3ZfMzAwPC1kYXRhLmZyYW1lKGNvdj1jKGN2WzE6Ml0sImNvdjIzLVBUIiwiY292MjMtUFMiLCJjb3YyMy1TVCIgLCJjb3YyMy0zIikpCmZvciAoaSBpbiAxOmxlbmd0aChjdikpewogICAgZGY8LXJlYWQuY3N2KHBhc3RlMCgiLi4vT3V0cHV0L0NPVi9DT1ZzY2FuXzNwb3AvM3BvcHNfdG9wMXBlcmNlbnRfb3V0bGllcl9yZWdpb25zLiIsIGN2W2ldLCAiX25ldy5jc3YiKSkKICAgIGRmPC1kZltkZiR3aW5kb3c9PSIxMDBrIixdCiAgICBkZiRpZDwtcGFzdGUwKGRmJGNocm9tLCJfIixkZiRzdGFydCkKICAgIAogICAgaWYgKGkhPTMpewogICAgICAgICNleGFjdCBvdmVybGFwcwogICAgICAgIGlzZWM8LWludGVyc2VjdChkZiRpZFtkZiRwb3A9PSJQV1MiXSwgZGYkaWRbZGYkcG9wPT0iVEIiXSkgCiAgICAgICAgT3ZfZGlyZWN0JGNvdW50W2ldPC1sZW5ndGgoaXNlYykKICAgICAgICAKICAgICAgICAjIyMjIENoZWNrIGNocm9tb3NvbWUgcmVnaW9uIG92ZXJsYXAgKy0yMDAsMDAwIGJhc2VzCiAgICAgICAgcG9wMTwtZGZbZGYkcG9wPT0iUFdTIixdCiAgICAgICAgcG9wMjwtZGZbZGYkcG9wPT0iVEIiLF0KICAgICAgICBvdmVybHBzPC1kYXRhLmZyYW1lKCkKICAgICAgICBvdmVybHBzMjwtZGF0YS5mcmFtZSgpCiAgICAgICAgZm9yIChuIGluIDE6IG5yb3cocG9wMSkpewogICAgICAgICAgICByZTwtcG9wMltwb3AyJGNocm9tPT1wb3AxJGNocm9tW25dLF0KICAgICAgICAgICAgaWYgKG5yb3cocmUpPj0xKXsKICAgICAgICAgICAgICAgIGZvciAocyBpbiAxOiBucm93KHJlKSl7CiAgICAgICAgICAgICAgICAgICAgaWYgKHJlJHN0YXJ0W3NdPD1wb3AxJHN0YXJ0W25dKzMwMDAwMCAmIHJlJHN0YXJ0W3NdPj1wb3AxJHN0YXJ0W25dLTMwMDAwMCl7CiAgICAgICAgICAgICAgICAgICAgICAgIG92ZXJscHM8LXJiaW5kKG92ZXJscHMsIHJlW3MsXSkKICAgICAgICAgICAgICAgICAgICAgICAgb3ZlcmxwczI8LXJiaW5kKG92ZXJscHMyLHBvcDFbbixdKX0KICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgfQogICAgICAgIH0KICAgICAgICAjIE1lcmdlIHR3byB0YWJsZXMgaW50byBvbmUgc3VtbWFyeSBvdmVybGFwIHRhYmxlOgogICAgICAgIG92PC1kYXRhLmZyYW1lKGlkPW92ZXJscHMkaWQpCiAgICAgICAgZm9yIChuIGluIDE6IG5yb3cob3ZlcmxwcykpewogICAgICAgICAgICBpZiAob3ZlcmxwcyRzdGFydFtuXTxvdmVybHBzMiRzdGFydFtuXSkge292JHN0YXJ0W25dPC1vdmVybHBzJHN0YXJ0W25dOyBvdiRlbmRbbl08LW92ZXJscHMyJGVuZFtuXX0KICAgICAgICAgICAgaWYgKG92ZXJscHMkc3RhcnRbbl0+PW92ZXJscHMyJHN0YXJ0W25dKSB7b3Ykc3RhcnRbbl08LW92ZXJscHMyJHN0YXJ0W25dO292JGVuZFtuXTwtb3ZlcmxwcyRlbmRbbl19CiAgICAgICAgfQogICAgICAgIG92WywiY292LlBXUyJdPC1vdmVybHBzWyw0XQogICAgICAgIG92WywiY292LlRCIl08LW92ZXJscHMyWyw0XQogICAgICAgIHdyaXRlLmNzdihvdiwgcGFzdGUwKCIuLi9PdXRwdXQvQ09WL0NPVnNjYW5fM3BvcC9PdmVybGFwX3JlZ2lvbnNfIixjdltpXSwiX3BsdXNtaW51czMwMGsuY3N2IiksIHJvdy5uYW1lcyA9IEYpCiAgICAgICAgT3ZfMzAwJGNvdW50W2ldPC1ucm93KG92KQogICAgICAgIH0KICAgICAgICAKICAgIGlmIChpPT0zKXsKICAgICAgICBpc2VjPC1pbnRlcnNlY3QoZGYkaWRbZGYkcG9wPT0iUFdTIl0sIGRmJGlkW2RmJHBvcD09IlRCIl0pIAogICAgICAgIGlzZWMyPC1pbnRlcnNlY3QoZGYkaWRbZGYkcG9wPT0iUFdTIl0sIGRmJGlkW2RmJHBvcD09IlNTIl0pIAogICAgICAgIGlzZWMzPC1pbnRlcnNlY3QoZGYkaWRbZGYkcG9wPT0iU1MiXSwgZGYkaWRbZGYkcG9wPT0iVEIiXSkgCiAgICAgICAgT3ZfZGlyZWN0JGNvdW50W2ldPC1sZW5ndGgoaXNlYykKICAgICAgICBPdl9kaXJlY3QkY291bnRbaSsxXTwtbGVuZ3RoKGlzZWMyKQogICAgICAgIE92X2RpcmVjdCRjb3VudFtpKzJdPC1sZW5ndGgoaXNlYykKICAgICAgICBPdl9kaXJlY3QkY291bnRbaSszXTwtbGVuZ3RoKGludGVyc2VjdChkZiRpZFtkZiRwb3A9PSJTUyJdLCBpbnRlcnNlY3QoZGYkaWRbZGYkcG9wPT0iUFdTIl0sIGRmJGlkW2RmJHBvcD09IlRCIl0pKSkKICAgICAgICAKICAgICAgICBmb3IoaiBpbiAxOm5yb3cocGFpcnMpKXsKICAgICAgICAjIyMjIENoZWNrIGNocm9tb3NvbWUgcmVnaW9uIG92ZXJsYXAgKy0yMDAsMDAwIGJhc2VzCiAgICAgICAgICAgIHBvcDE8LWRmW2RmJHBvcD09cGFpcnNbaiwxXSxdCiAgICAgICAgICAgIHBvcDI8LWRmW2RmJHBvcD09cGFpcnNbaiwyXSxdCiAgICAgICAgICAgIG92ZXJscHM8LWRhdGEuZnJhbWUoKQogICAgICAgICAgICBvdmVybHBzMjwtZGF0YS5mcmFtZSgpCiAgICAgICAgICAgIGZvciAobiBpbiAxOiBucm93KHBvcDEpKXsKICAgICAgICAgICAgICAgIHJlPC1wb3AyW3BvcDIkY2hyb209PXBvcDEkY2hyb21bbl0sXQogICAgICAgICAgICAgICAgaWYgKG5yb3cocmUpPj0xKXsKICAgICAgICAgICAgICAgICAgICBmb3IgKHMgaW4gMTogbnJvdyhyZSkpewogICAgICAgICAgICAgICAgICAgICAgICBpZiAocmUkc3RhcnRbc108PXBvcDEkc3RhcnRbbl0rMzAwMDAwICYgcmUkc3RhcnRbc10+PXBvcDEkc3RhcnRbbl0tMzAwMDAwKXsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIG92ZXJscHM8LXJiaW5kKG92ZXJscHMsIHJlW3MsXSkKICAgICAgICAgICAgICAgICAgICAgICAgICAgIG92ZXJscHMyPC1yYmluZChvdmVybHBzMixwb3AxW24sXSl9CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgfQogICAgICAgICAgICB9CiAgICAgICAgIyBNZXJnZSB0d28gdGFibGVzIGludG8gb25lIHN1bW1hcnkgb3ZlcmxhcCB0YWJsZToKICAgICAgICAgICAgb3Y8LWRhdGEuZnJhbWUoaWQ9b3ZlcmxwcyRpZCkKICAgICAgICAgICAgZm9yIChuIGluIDE6IG5yb3cob3ZlcmxwcykpewogICAgICAgICAgICAgICAgaWYgKG92ZXJscHMkc3RhcnRbbl08b3ZlcmxwczIkc3RhcnRbbl0pIHtvdiRzdGFydFtuXTwtb3ZlcmxwcyRzdGFydFtuXTsgb3YkZW5kW25dPC1vdmVybHBzMiRlbmRbbl19CiAgICAgICAgICAgICAgICBpZiAob3ZlcmxwcyRzdGFydFtuXT49b3ZlcmxwczIkc3RhcnRbbl0pIHtvdiRzdGFydFtuXTwtb3ZlcmxwczIkc3RhcnRbbl07b3YkZW5kW25dPC1vdmVybHBzJGVuZFtuXX0KICAgICAgICAgICAgfQogICAgICAgIAogICAgICAgICAgICBvdlsscGFzdGUwKCJjb3YuIixwYWlyc1tqLDFdKV08LW92ZXJscHNbLDRdCiAgICAgICAgICAgIG92WyxwYXN0ZTAoImNvdi4iLHBhaXJzW2osMl0pXTwtb3ZlcmxwczJbLDRdCiAgICAgICAgICAgIG92PC1vdlshZHVwbGljYXRlZChvdiksXQogICAgICAgICAgICB3cml0ZS5jc3Yob3YsIHBhc3RlMCgiLi4vT3V0cHV0L0NPVi9DT1ZzY2FuXzNwb3AvT3ZlcmxhcF9yZWdpb25zXyIsY3ZbaV0sIl8iLHBhaXJzW2osMV0sIi4iLCBwYWlyc1tqLDJdLCJfcGx1c21pbnVzMzAway5jc3YiKSwgcm93Lm5hbWVzID0gRikKICAgICAgICAgICAgT3ZfMzAwJGNvdW50W2krai0xXTwtbnJvdyhvdikKICAgIH0KICAgIH0KfQp3cml0ZS5jc3YoT3ZfZGlyZWN0LCBwYXN0ZTAoIi4uL091dHB1dC9DT1YvQ09Wc2Nhbl8zcG9wL0REaXJlY3RfT3ZlcmxhcHBpbmdfcmVnaW9uc19jb3VudHNfM3BvcF9zdW1tYXJ5LmNzdiIpKQpPdl8zMDAkY291bnRbNl08LU5BCndyaXRlLmNzdihPdl8zMDAsIHBhc3RlMCgiLi4vT3V0cHV0L0NPVi9DT1ZzY2FuXzNwb3AvT3ZlcmxhcHBpbmdfcmVnaW9uc19jb3VudHNfM3BvcF9wbHVzTWludXMzMDBrLmNzdiIpKQoKYGBgCgoKIyBSdW4gdGhlIHNucEVmZiBwaXBlbGluZSB0byBmaW5kIGFubm90YXRpb24gaW4gdGhlIG91dGxpZXIgcmVnaW9ucyAoMTAway13aW5kb3crLTEwMGspICAKCiMjIENyZWF0ZSBhIHNjcmlwdCB0byBydW4gU25wRWZmIAoKQ3JlYXRlIFZDRiBmaWxlcyB3aXRoIHNlbGVjdGVkIHJlZ2lvbnMgJiBydW4gc25wRWZmICAKYGBge3IgZXZhbD1GQUxTRSwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KI0NyZWF0ZSBiZWQgZmlsZXMKY3Y8LWMoImNvdjEyIiwiY292MTMiLCJjb3YyMyIpCiNQcmV2ZW50IHNjaWVudGlmaWMgbm90YXRpb24gaW4gYmVkIGZpbGVzCm9wdGlvbnMoc2NpcGVuPTk5OSkKCiNUaGUgZmlyc3QgbGluZSBvZiBiZWQgZmlsZXMgaXMgb2Z0ZW4gbm90IHJlZCBieSB2Y2Z0b29scwpmb3IgKGkgaW4gMTozKXsKICAgIGRmPC1yZWFkLmNzdihwYXN0ZTAoIi4uL091dHB1dC9DT1YvQ09Wc2Nhbl8zcG9wLzNwb3BzX3RvcDFwZXJjZW50X291dGxpZXJfcmVnaW9ucy4iLGN2W2ldLCJfbmV3LmNzdiIpKQogICAgI3NlbGVjdCAxMDBrCiAgICBkZjwtZGZbZGYkd2luZG93PT0iMTAwayIsXQogICAgI2FkZCAxMDBrCiAgICBkZiRzdGFydDwtZGYkc3RhcnQtMTAwMDAwCiAgICBkZiRlbmQ8LWRmJGVuZCsxMDAwMDAKICAgIGRmcDwtZGZbZGYkcG9wPT0iUFdTIiwxOjNdCiAgICBjb2xuYW1lcyhkZnApPC1jKCd0cmFjayB0eXBlPWJlZEdyYXBoJywgJzEnLCcxJykKICAgIHdyaXRlLnRhYmxlKGRmcCwgcGFzdGUwKCIuLi9PdXRwdXQvQ09WL0NPVnNjYW5fM3BvcC9QV1Nfb3V0bGllcnNfIixjdltpXSwiX25ldy5iZWQiKSxxdW90ZSA9IEYsIHJvdy5uYW1lcyA9IEYsIGNvbC5uYW1lcyA9IFQsc2VwID0gIlx0IikKICAgIGRmdDwtZGZbZGYkcG9wPT0iVEIiLDE6M10KICAgIGNvbG5hbWVzKGRmdCk8LWMoJ3RyYWNrIHR5cGU9YmVkR3JhcGgnLCAnMScsJzEnKQogICAgd3JpdGUudGFibGUoZGZ0LCBwYXN0ZTAoIi4uL091dHB1dC9DT1YvQ09Wc2Nhbl8zcG9wL1RCX291dGxpZXJzXyIsY3ZbaV0sIl9uZXcuYmVkIikscXVvdGUgPSBGLCByb3cubmFtZXMgPSBGLCBjb2wubmFtZXMgPSBGLHNlcCA9ICJcdCIpCiAgICAKICAgIGlmIChpPT0zKXsKICAgICAgICBkZnM8LWRmW2RmJHBvcD09IlNTIiwxOjNdCiAgICAgICAgY29sbmFtZXMoZGZzKTwtYygndHJhY2sgdHlwZT1iZWRHcmFwaCcsICcxJywnMScpCiAgICAgICAgd3JpdGUudGFibGUoZGZzLCBwYXN0ZTAoIi4uL091dHB1dC9DT1YvQ09Wc2Nhbl8zcG9wL1NTX291dGxpZXJzXyIsY3ZbaV0sIl9uZXcuYmVkIikscXVvdGUgPSBGLCByb3cubmFtZXMgPSBGLCBjb2wubmFtZXMgPSBGLHNlcCA9ICJcdCIpCiAgICB9Cn0KCiNmb3IgNTBrIGFuZCA3NWsgaW4gUFdTCmZvciAoaSBpbiAxOjMpewogICAgZGY8LXJlYWQuY3N2KHBhc3RlMCgiLi4vT3V0cHV0L0NPVi9DT1ZzY2FuXzNwb3AvM3BvcHNfdG9wMXBlcmNlbnRfb3V0bGllcl9yZWdpb25zLiIsY3ZbaV0sIl9uZXcuY3N2IikpCiAgICBkZjwtZGZbZGYkcG9wPT0iUFdTIixdCiAgICBkZiRzdGFydDwtZGYkc3RhcnQtMTAwMDAwCiAgICBkZiRlbmQ8LWRmJGVuZCsxMDAwMDAKICAgIGRmNTA8LWRmW2RmJHdpbmRvdz09IjUwayIsMTozXQogICAgZGY3NTwtZGZbZGYkd2luZG93PT0iNzVrIiwxOjNdCiAgICBjb2xuYW1lcyhkZjUwKTwtYygndHJhY2sgdHlwZT1iZWRHcmFwaCcsICcxJywnMScpCiAgICBjb2xuYW1lcyhkZjc1KTwtYygndHJhY2sgdHlwZT1iZWRHcmFwaCcsICcxJywnMScpCiAgICAKICAgIHdyaXRlLnRhYmxlKGRmNTAsIHBhc3RlMCgiLi4vT3V0cHV0L0NPVi9DT1ZzY2FuXzNwb3AvUFdTX291dGxpZXJzXyIsY3ZbaV0sIl81MGsuYmVkIikscXVvdGUgPSBGLCByb3cubmFtZXMgPSBGLCBjb2wubmFtZXMgPSBULHNlcCA9ICJcdCIpCiAgICB3cml0ZS50YWJsZShkZjc1LCBwYXN0ZTAoIi4uL091dHB1dC9DT1YvQ09Wc2Nhbl8zcG9wL1BXU19vdXRsaWVyc18iLGN2W2ldLCJfNzVrLmJlZCIpLHF1b3RlID0gRiwgcm93Lm5hbWVzID0gRiwgY29sLm5hbWVzID0gVCxzZXAgPSAiXHQiKQp9CgojIENyZWF0ZSBhIGJhc2ggc2NyaXB0IHRvIHJ1biBzbnBFZmYKYmVkZmlsZXM8LWxpc3QuZmlsZXMoIi4uL091dHB1dC9DT1YvQ09Wc2Nhbl8zcG9wLyIsIHBhdHRlcm49IipfbmV3LmJlZCIpCgpzaW5rKCIuLi9DT1ZzY2FuX2NyZWF0ZVZDRnNfM1BvcHMyLnNoIikKY2F0KCIjIS9iaW4vYmFzaCBcblxuIikKZm9yIChpIGluIDE6bGVuZ3RoKGJlZGZpbGVzKSl7CiAgICBmbmFtZTwtZ3N1YigiLmJlZCIsJycsIGJlZGZpbGVzW2ldKQogICAgY2F0KHBhc3RlMCgidmNmdG9vbHMgLS1nenZjZiBEYXRhL25ld192Y2YvM3BvcC8zcG9wcy5NRDcwMDBfTlMwLjVfbWFmMDUudmNmLmd6IC0tYmVkIE91dHB1dC9DT1YvQ09Wc2Nhbl8zcG9wLyIsIGJlZGZpbGVzW2ldLCAiIC0tb3V0IE91dHB1dC9DT1YvQ09Wc2Nhbl8zcG9wLyIsIGZuYW1lLCIgLS1yZWNvZGUgLS1rZWVwLUlORk8tYWxsIFxuIikpCn0Kc2luayhOVUxMKSAgCgojY3JlYXRlIGEgYmFzaCBzY3JpcHQgdG8gcnVuIHNucEVmZgp2ZmlsZXM8LWxpc3QuZmlsZXMoIi4uL091dHB1dC9DT1YvQ09Wc2Nhbl8zcG9wLyIsIHBhdHRlcm49Ii5yZWNvZGUudmNmIikKCnNpbmsoIn4vcHJvZ3JhbXMvc25wRWZmL3J1bnNucEVmZl9jb3ZfM3BvcC5zaCIpCmNhdCgiIyEvYmluL2Jhc2ggXG5cbiIpCmZvciAoaSBpbiAxOmxlbmd0aCh2ZmlsZXMpKXsKICAgIGZuYW1lPC1nc3ViKCJfbmV3LnJlY29kZS52Y2YiLCIiLHZmaWxlc1tpXSkKICAgIGNhdChwYXN0ZTAoImphdmEgLVhteDhnIC1qYXIgc25wRWZmLmphciBDaF92Mi4wLjIuOTkgfi9Qcm9qZWN0cy9QYWNIZXJyaW5nL091dHB1dC9DT1YvQ09Wc2Nhbl8zcG9wLyIsdmZpbGVzW2ldLCAiIC1zdGF0cyB+L1Byb2plY3RzL1BhY0hlcnJpbmcvT3V0cHV0L0NPVi9DT1ZzY2FuXzNwb3AvIixmbmFtZSwiLmh0bWwgPiAgfi9Qcm9qZWN0cy9QYWNIZXJyaW5nL091dHB1dC9DT1YvQ09Wc2Nhbl8zcG9wL0Fubm8uIixmbmFtZSwiLnZjZiBcbiIpKQogICAgCiAgICAjZXh0cmFjdCB0aGUgYW5ub3RhdGlvbiBpbmZvcm1hdGlvbgogICAgY2F0KHBhc3RlMCgiYmNmdG9vbHMgcXVlcnkgLWYgJyVDSFJPTSAlUE9TICVJTkZPL0FGICVJTkZPL0FOTlxcbicgfi9Qcm9qZWN0cy9QYWNIZXJyaW5nL091dHB1dC9DT1YvQ09Wc2Nhbl8zcG9wL0Fubm8uIixmbmFtZSwiLnZjZiA+IH4vUHJvamVjdHMvUGFjSGVycmluZy9PdXRwdXQvQ09WL0NPVnNjYW5fM3BvcC8iLGZuYW1lLCJfYW5ub3RhdGlvbiBcblxuIikpCgp9CnNpbmsoTlVMTCkgIAoKCmBgYAoKYGBge2Jhc2ggZXZhbD1GQUxTRSwgaW5jbHVkZT1GQUxTRX0KY2Qgfi9Qcm9qZWN0cy9QYWNIZXJyaW5nCmJhc2ggQ09Wc2Nhbl9jcmVhdGVWQ0ZzXzNwb3BzLnNoCgpjZCB+L3Byb2dyYW1zL3NucEVmZgpiYXNoIHJ1bnNucEVmZl9jb3ZfM3BvcC5zaApgYGAKCgojIyBDcmVhdGUgc3VtbWFyeSBnZW5lIGZpbGVzIGZyb20gc25wRWZmIGFuZCBjaGVjayBvdmVybGFwcGluZyBnZW5lcy4KCmBgYHtyIGV2YWw9RkFMU0UsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CiMjIENyZWF0ZSBzdW1tYXJ5IGZpbGVzIG9mIHNucEVmZiByZXN1bHRzIChnZW5lIGFubm90YXRpb25zIGluIHRoZSByZWdpb25zIG9mIGludGVyZXN0KSBhbmQgcmVmb3JtYXQgYXMgYSBTaGlueUdvIGlucHV0IAoKI2NyZWF0ZSBnZW5lIGxpc3QgZm9yIFNoaW55R28KZ2ZpbGVzPC1saXN0LmZpbGVzKCIuLi9PdXRwdXQvQ09WL0NPVnNjYW5fM3BvcC8iLCBwYXR0ZXJuPSJnZW5lcy50eHQiKQoKZm9yIChpIGluIDE6bGVuZ3RoKGdmaWxlcykpewogICAgZGY8LXJlYWQudGFibGUocGFzdGUwKCIuLi9PdXRwdXQvQ09WL0NPVnNjYW5fM3BvcC8iLGdmaWxlc1tpXSksIHNlcD0iXHQiKQogICAgZGY8LWRmWywxOjddCiAgICBjb2xuYW1lcyhkZik8LWMoIkdlbmVOYW1lIiwiR2VuZUlkIiwiVHJhbnNjcmlwdElkIiwiQmlvVHlwZSIsInZhcmlhbnRzX2ltcGFjdF9ISUdIIiwidmFyaWFudHNfaW1wYWN0X0xPVyIsCSJ2YXJpYW50c19pbXBhY3RfTU9ERVJBVEUiKQogICAgCiAgICBmbmFtZTwtZ3N1YigiLmdlbmVzLnR4dCIsIiIsZ2ZpbGVzW2ldKQogICAgZ2VuZXM8LXVuaXF1ZShkZiRHZW5lSWQpCiAgICBzaW5rKHBhc3RlMCgiLi4vT3V0cHV0L0NPVi9DT1ZzY2FuXzNwb3AvZ2VuZUlEbGlzdF8iLGZuYW1lLCIudHh0IikpCiAgICBjYXQocGFzdGUwKGdlbmVzLCI7ICIpKQogICAgc2luayhOVUxMKQp9CgojQW5ub3RhdGlvbiBpbmZvciBmcm9tIFNucEVmZgpmb3IgKGMgaW4gMTozKXsKICAgIGlmIChjIT0zKXsKICAgIGZvciAocCBpbiAxOjIpewogICAgICAgIGFubzwtcmVhZC50YWJsZShwYXN0ZTAoIi4uL091dHB1dC9DT1YvQ09Wc2Nhbl8zcG9wLyIscG9wc1twXSwiX291dGxpZXJzXyIsY3ZbY10sIl9hbm5vdGF0aW9uIiksIGhlYWRlciA9IEYpCiAgICAgICAgYW5ub3RhdGlvbnM8LWRhdGEuZnJhbWUoKQogICAgICAgIGZvciAoaSBpbiAxOiBucm93KGFubykpewogICAgICAgICAgICBhbm5zPC11bmxpc3Qoc3Ryc3BsaXQoYW5vJFY0W2ldLCAiXFwsfFxcfCIpKQogICAgICAgICAgICBhbm5tPC1kYXRhLmZyYW1lKG1hdHJpeChhbm5zLG5jb2wgPSAxNiwgYnlyb3cgPSBUUlVFKSkKICAgICAgICAgICAgYW5ubTwtYW5ubVssYygyLDMsNCw1LDgpXQogICAgICAgICAgICBjb2xuYW1lcyhhbm5tKTwtYygiRWZmZWN0IiwiUHV0YXRpdmVfaW1wYWN0IiwiR2VuZV9uYW1lIiwiR2VuZV9JRCIsIkZlYXR1cmUgdHlwZSIpCiAgICAgICAgICAgIGFubm08LWFubm1bIWR1cGxpY2F0ZWQoYW5ubSksIF0KICAgICAgICAgICAgYW5ubSRjaHI8LWFubyRWMVtpXQogICAgICAgICAgICBhbm5tJGNocjwtYW5vJFYxW2ldCiAgICAgICAgICAgIGFubm0kcG9zPC1hbm8kVjJbaV0KICAgICAgICAgICAgYW5ubSRBRjwtIGFubyRWM1tpXQogICAgICAgICAgICBhbm5vdGF0aW9uczwtcmJpbmQoYW5ub3RhdGlvbnMsIGFubm0pCiAgICAgICAgfSAgICAgCiAgICAgICAgYW5ub3RhdGlvbnM8LWFubm90YXRpb25zWyxjKDY6OCwxOjUpXQogICAgICAgIGFubm90YXRpb25zPC1hbm5vdGF0aW9uc1shZHVwbGljYXRlZChhbm5vdGF0aW9uc1ssMToyXSksXQogICAgICAgIHdyaXRlLmNzdihhbm5vdGF0aW9ucywgcGFzdGUwKCIuLi9PdXRwdXQvQ09WL0NPVnNjYW5fM3BvcC9HZW5lc18iLHBvcHNbcF0sIl9vdXRsaWVyc18xMDBrXyIsY3ZbY10sIi5jc3YiKSwgcm93Lm5hbWVzID0gRikKICAgIH0KICAgIH0KICAgIGlmIChjPT0zKXsKICAgICAgICBmb3IgKHAgaW4gMTozKXsKICAgICAgICBhbm88LXJlYWQudGFibGUocGFzdGUwKCIuLi9PdXRwdXQvQ09WL0NPVnNjYW5fM3BvcC8iLHBvcHNbcF0sIl9vdXRsaWVyc18iLGN2W2NdLCJfYW5ub3RhdGlvbiIpLCBoZWFkZXIgPSBGKQogICAgICAgIGFubm90YXRpb25zPC1kYXRhLmZyYW1lKCkKICAgICAgICBmb3IgKGkgaW4gMTogbnJvdyhhbm8pKXsKICAgICAgICAgICAgYW5uczwtdW5saXN0KHN0cnNwbGl0KGFubyRWNFtpXSwgIlxcLHxcXHwiKSkKICAgICAgICAgICAgYW5ubTwtZGF0YS5mcmFtZShtYXRyaXgoYW5ucyxuY29sID0gMTYsIGJ5cm93ID0gVFJVRSkpCiAgICAgICAgICAgIGFubm08LWFubm1bLGMoMiwzLDQsNSw4KV0KICAgICAgICAgICAgY29sbmFtZXMoYW5ubSk8LWMoIkVmZmVjdCIsIlB1dGF0aXZlX2ltcGFjdCIsIkdlbmVfbmFtZSIsIkdlbmVfSUQiLCJGZWF0dXJlIHR5cGUiKQogICAgICAgICAgICBhbm5tPC1hbm5tWyFkdXBsaWNhdGVkKGFubm0pLCBdCiAgICAgICAgICAgIGFubm0kY2hyPC1hbm8kVjFbaV0KICAgICAgICAgICAgYW5ubSRjaHI8LWFubyRWMVtpXQogICAgICAgICAgICBhbm5tJHBvczwtYW5vJFYyW2ldCiAgICAgICAgICAgIGFubm0kQUY8LSBhbm8kVjNbaV0KICAgICAgICAgICAgYW5ub3RhdGlvbnM8LXJiaW5kKGFubm90YXRpb25zLCBhbm5tKQogICAgICAgIH0gICAgIAogICAgICAgIGFubm90YXRpb25zPC1hbm5vdGF0aW9uc1ssYyg2OjgsMTo1KV0KICAgICAgICBhbm5vdGF0aW9uczwtYW5ub3RhdGlvbnNbIWR1cGxpY2F0ZWQoYW5ub3RhdGlvbnNbLDE6Ml0pLF0KICAgICAgICB3cml0ZS5jc3YoYW5ub3RhdGlvbnMsIHBhc3RlMCgiLi4vT3V0cHV0L0NPVi9DT1ZzY2FuXzNwb3AvR2VuZXNfIixwb3BzW3BdLCJfb3V0bGllcnNfMTAwa18iLGN2W2NdLCIuY3N2IiksIHJvdy5uYW1lcyA9IEYpCiAgICB9Cn0KICAKfQoKYGBgCgoKIyMgRmluZCB0aGUgaW50ZXJzZWN0aW5nIGdlbmUgbmFtZXMgYWNyb3NzIHRpbWUgcG9pbnRzIHdpdGhpbiBhIHBvcHVsYXRpb24KCmBgYHtyIGV2YWw9RkFMU0UsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CgojIEZpbmQgdGhlIGludGVyc2VjdGluZyBnZW5lIG5hbWVzIGFjcm9zcyB0aW1lIHBvaW50cwpnZmlsZXMyPC1saXN0LmZpbGVzKCIuLi9PdXRwdXQvQ09WL0NPVnNjYW5fM3BvcC8iLCBwYXR0ZXJuPSJnZW5lSURsaXN0IikKZ2xpc3Q8LWxpc3QoKQpmb3IgKGkgaW4gMTpsZW5ndGgoZ2ZpbGVzKSl7CiAgICBkZjwtcmVhZC50YWJsZShwYXN0ZTAoIi4uL091dHB1dC9DT1YvQ09Wc2Nhbl8zcG9wLyIsZ2ZpbGVzMltpXSksIHNlcD0iOyIpCiAgICBkZjwtdChkZikKICAgIGRmPC1nc3ViKCIgIiwiIixkZikKICAgIGRmMjwtZGZbIWlzLm5hKGRmKV0KICAgIHZuYW1lPC1nc3ViKCIudHh0IiwiIixnZmlsZXMyW2ldLCkKICAgIHZuYW1lPC1nc3ViKCJnZW5lSURsaXN0XyIsIiIsIHZuYW1lKQogICAgZ2xpc3RbW2ldXTwtZGYyCiAgICBuYW1lcyhnbGlzdClbaV08LXZuYW1lCn0KCnRpbWVzPC1jKCJjb3YxMiIsImNvdjEzIiwiY292MjMiKQpjb21tb248LWxpc3QoKQpjb21tb25fZ2VuZXM8LWRhdGEuZnJhbWUodGltZT10aW1lcykKZm9yIChpIGluIDE6Myl7CiAgICB0bGlzdDwtZ2xpc3RbZ3JlcCh0aW1lc1tpXSwgbmFtZXMoZ2xpc3QpKV0KICAgIGlmIChpICE9Myl7CiAgICAgICAgY29tbW9uW1tpXV08LWludGVyc2VjdCh0bGlzdFtbMV1dLCB0bGlzdFtbMl1dKQogICAgICAgIG5hbWVzKGNvbW1vbilbW2ldXTwtdGltZXNbaV0KICAgICAgICBjb21tb25fZ2VuZXMkUFdTW2ldPC1sZW5ndGgodGxpc3RbW2dyZXAoIlBXUyIsIG5hbWVzKHRsaXN0KSldXSkKICAgICAgICBjb21tb25fZ2VuZXMkVEJbaV08LWxlbmd0aCh0bGlzdFtbZ3JlcCgiVEIiLCBuYW1lcyh0bGlzdCkpXV0pCiAgICAgICAgY29tbW9uX2dlbmVzJFNTW2ldPC1OQQogICAgICAgIGNvbW1vbl9nZW5lcyRjb21tb25fUFdTLlRCW2ldPC1sZW5ndGgoaW50ZXJzZWN0KHRsaXN0W1sxXV0sIHRsaXN0W1syXV0pKQogICAgfQogICAgaWYgKGk9PTMpewogICAgICAgIGNvbW1vbl9nZW5lcyRQV1NbaV08LWxlbmd0aCh0bGlzdFtbZ3JlcCgiUFdTIiwgbmFtZXModGxpc3QpKV1dKQogICAgICAgIGNvbW1vbl9nZW5lcyRUQltpXTwtbGVuZ3RoKHRsaXN0W1tncmVwKCJUQiIsIG5hbWVzKHRsaXN0KSldXSkKICAgICAgICBjb21tb25fZ2VuZXMkU1NbaV08LWxlbmd0aCh0bGlzdFtbZ3JlcCgiU1MiLCBuYW1lcyh0bGlzdCkpXV0pCiAgICAgICAgY29tbW9uX2dlbmVzJGNvbW1vbl9QV1MuVEJbaV08LWxlbmd0aChpbnRlcnNlY3QodGxpc3RbWzFdXSwgdGxpc3RbWzNdXSkpCiAgICAgICAgY29tbW9uX2dlbmVzJGNvbW1vbl9QV1MuU1NbaV08LWxlbmd0aChpbnRlcnNlY3QodGxpc3RbWzFdXSwgdGxpc3RbWzJdXSkpCiAgICAgICAgY29tbW9uX2dlbmVzJGNvbW1vbl9TUy5UQltpXTwtbGVuZ3RoKGludGVyc2VjdCh0bGlzdFtbMl1dLCB0bGlzdFtbM11dKSkKICAgICAgICBjb21tb25fZ2VuZXMkY29tbW9uM1tpXTwtbGVuZ3RoKGludGVyc2VjdCh0bGlzdFtbMV1dLGludGVyc2VjdCh0bGlzdFtbMl1dLCB0bGlzdFtbM11dKSkpCiAgICAgICAgaz1pCiAgICAgICAgY29tbW9uW1trXV08LWludGVyc2VjdCh0bGlzdFtbMV1dLCB0bGlzdFtbMl1dKQogICAgICAgIG5hbWVzKGNvbW1vbilbW2tdXTwtcGFzdGUwKHRpbWVzW2ldLCJfUFdTLlNTIikKICAgICAgICBrPWsrMQogICAgICAgIGNvbW1vbltba11dPC1pbnRlcnNlY3QodGxpc3RbWzFdXSwgdGxpc3RbWzNdXSkKICAgICAgICBuYW1lcyhjb21tb24pW1trXV08LXBhc3RlMCh0aW1lc1tpXSwiX1BXUy5UQiIpCiAgICAgICAgaz1rKzEKICAgICAgICBjb21tb25bW2tdXTwtaW50ZXJzZWN0KHRsaXN0W1syXV0sIHRsaXN0W1szXV0pCiAgICAgICAgbmFtZXMoY29tbW9uKVtba11dPC1wYXN0ZTAodGltZXNbaV0sIl9TUy5UQiIpCiAgICAgICAgaz1rKzEKICAgICAgICBjb21tb25bW2tdXTwtaW50ZXJzZWN0KHRsaXN0W1sxXV0saW50ZXJzZWN0KHRsaXN0W1syXV0sIHRsaXN0W1szXV0pKQogICAgICAgIG5hbWVzKGNvbW1vbilbW2tdXTwtcGFzdGUwKHRpbWVzW2ldLCJfM3BvcHMiKQogICAgICAgIH0KfQogICAgCndyaXRlLmNzdihjb21tb25fZ2VuZXMsICIuLi9PdXRwdXQvQ09WL0NPVnNjYW5fM3BvcC9Db21tb25fZ2VuZXNfM3BvcHMuY3N2IikKCgojV2hhdCBhcmUgdGhlIG92ZXJsYXBwaW5nIGdlbmUgbmFtZXMKI2FnZ3JlZ2F0ZSBhbGwgZ2VuZSBuYW1lcwpHZW5lczwtZGF0YS5mcmFtZSgpCmZvciAoaSBpbiAxOmxlbmd0aChnZmlsZXMpKXsKICAgIGRmPC1yZWFkLnRhYmxlKHBhc3RlMCgiLi4vT3V0cHV0L0NPVi9DT1ZzY2FuXzNwb3AvIixnZmlsZXNbaV0pLCBzZXA9Ilx0IikKICAgIGRmPC1kZlssMToyXQogICAgY29sbmFtZXMoZGYpPC1jKCJHZW5lTmFtZSIsIkdlbmVJZCIpCiAgICBkZjwtZGZbIWR1cGxpY2F0ZWQoZGYpLF0KICAgIEdlbmVzPC1yYmluZChHZW5lcywgZGYpCiAgICBHZW5lczwtR2VuZXNbIWR1cGxpY2F0ZWQoR2VuZXMpLF0KfQoKZm9yIChpIGluIDE6IGxlbmd0aChjb21tb24pKXsKICAgIGdpZHM8LWNvbW1vbltbaV1dCiAgICBkZjwtZGF0YS5mcmFtZShHZW5lSWQ9Z2lkcykKICAgIAogICAgZGY8LW1lcmdlKGRmLCBHZW5lcywgYnk9IkdlbmVJZCIpCiAgICB3cml0ZS5jc3YoZGYsIHBhc3RlMCgiLi4vT3V0cHV0L0NPVi9DT1ZzY2FuXzNwb3AvQ29tbW9uX2dlbmVzXyIsIG5hbWVzKGNvbW1vbilbaV0sIi5jc3YiKSwgcm93Lm5hbWVzID0gRikKfQpgYGAKCgoKIyMjIyBPdmVybGFwcGluZyBnZW5lIG51bWJlcnMgICAKYGBge3IgZWNobz1GQUxTRSwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KCiMgU3VtbWFyeSB0YWJsZQpjb21tb25fZ2VuZXM8LXJlYWQuY3N2KCIuLi9PdXRwdXQvQ09WL0NPVnNjYW5fM3BvcC9Db21tb25fZ2VuZXNfM3BvcHMuY3N2Iiwgcm93Lm5hbWVzID0gMSkKa25pdHI6OmthYmxlKGNvbW1vbl9nZW5lcykKCmBgYAoKCgpgYGB7ciBldmFsPUZBTFNFLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQoKIyMgQ2hlY2sgY2hyb21vc29tZSBvdmVybGFwCgoKCgpgYGAKCgoKIyBDb21wYXJlIHJlc3VsdHMgZnJvbSBQSF9NRDcwMDAgKGFsbCBwb3BzIHRvZ2V0aGVyKSBhbmQgM1BvcHMtTlMwLjUgKGZpbHRlciBmb3IgMyBwb3BzKSBWQ0YgZmlsZXMgIAoKYGBge3IgZXZhbD1GQUxTRSwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KcHdzMTwtcmVhZC5jc3YoIi4uL091dHB1dC9DT1YvQ09Wc2Nhbl8zcG9wLzNwb3BzX3RvcDFwZXJjZW50X291dGxpZXJfcmVnaW9ucy5jb3YxMl9uZXcuY3N2IikKcHdzMTwtcHdzMVtwd3MxJHBvcD09IlBXUyIgJiBwd3MxJHdpbmRvdz09IjEwMGsiLF0KcHdzMjwtcmVhZC5jc3YoIi4uL091dHB1dC9DT1YvM3BvcHNfdG9wMXBlcmNlbnRfb3V0bGllcl9yZWdpb25zLmNvdjEyLmNzdiIpCnB3czI8LXB3czJbcHdzMiRwb3A9PSJQV1MiJnB3czIkd2luZG93PT0iMTAwayIsXQoKcHdzMSR2Y2Y8LSIzUG9wcyIKcHdzMiR2Y2Y8LSJQSCIKcHdzPC1yYmluZChwd3MxWyxjKCJjaHJvbSIsInN0YXJ0IiwiZW5kIiwiY292MTIiLCJ2Y2YiKV0scHdzMlssYygiY2hyb20iLCJzdGFydCIsImVuZCIsImNvdjEyIiwidmNmIildKQpwd3MkY2hyb208LWZhY3Rvcihwd3MkY2hyb20sIGxldmVscz1wYXN0ZTAoImNociIsIDE6MjYpKQpnZ3Bsb3QoZGF0YT1wd3MsYWVzKHg9c3RhcnQvMTAwMDAwMCwgeT1jb3YxMiwgY29sb3I9dmNmLCBmaWxsPXZjZikpKwogICAgZmFjZXRfd3JhcCh+Y2hyb20pKwogICAgZ2VvbV9wb2ludChwb3NpdGlvbj1wb3NpdGlvbl9kb2RnZSh3aWR0aCA9IDAuNyksIGFscGhhPTAuNSkreGxhYigiUG9zaXRpb24gKE1iKSIpKwogICAgZ2d0aXRsZSgiUFdTIENPVjEyIikKZ2dzYXZlKCIuLi9PdXRwdXQvQ09WL0NPVnNjYW5fM3BvcC9QV1NfUEgudnMuM1BvcHNfb3V0bGllcl9vdmVybGFwX2NvdjEyLnBuZyIsIHdpZHRoID0gMTAsIGhlaWdodCA9IDgsIGRwaT0zMDApCmBgYAohW10oLi4vT3V0cHV0L0NPVi9DT1ZzY2FuXzNwb3AvUFdTX1BILnZzLjNQb3BzX291dGxpZXJfb3ZlcmxhcF9jb3YxMi5wbmcpCgpgYGB7ciBldmFsPUZBTFNFLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQoKcHdzMTwtcmVhZC5jc3YoIi4uL091dHB1dC9DT1YvQ09Wc2Nhbl8zcG9wLzNwb3BzX3RvcDFwZXJjZW50X291dGxpZXJfcmVnaW9ucy5jb3YyM19uZXcuY3N2IikKcHdzMTwtcHdzMVtwd3MxJHBvcD09IlBXUyIgJiBwd3MxJHdpbmRvdz09IjEwMGsiLF0KcHdzMjwtcmVhZC5jc3YoIi4uL091dHB1dC9DT1YvM3BvcHNfdG9wMXBlcmNlbnRfb3V0bGllcl9yZWdpb25zLmNvdjIzLmNzdiIpCnB3czI8LXB3czJbcHdzMiRwb3A9PSJQV1MiJnB3czIkd2luZG93PT0iMTAwayIsXQoKcHdzMSR2Y2Y8LSJQSCIKcHdzMiR2Y2Y8LSIzUG9wcyIKcHdzPC1yYmluZChwd3MxWyxjKCJjaHJvbSIsInN0YXJ0IiwiZW5kIiwiY292MjMiLCJ2Y2YiKV0scHdzMlssYygiY2hyb20iLCJzdGFydCIsImVuZCIsImNvdjIzIiwidmNmIildKQpwd3MkY2hyb208LWZhY3Rvcihwd3MkY2hyb20sIGxldmVscz1wYXN0ZTAoImNociIsIDE6MjYpKQpnZ3Bsb3QoZGF0YT1wd3MsYWVzKHg9c3RhcnQvMTAwMDAwMCwgeT1jb3YyMywgY29sb3I9dmNmLCBmaWxsPXZjZikpKwogICAgZmFjZXRfd3JhcCh+Y2hyb20pKwogICAgZ2VvbV9wb2ludChwb3NpdGlvbj1wb3NpdGlvbl9kb2RnZSh3aWR0aCA9IDAuNyksIGFscGhhPTAuNSkreGxhYigiUG9zaXRpb24gKE1iKSIpKwogICAgZ2d0aXRsZSgiUFdTIENPVjIzIikKZ2dzYXZlKCIuLi9PdXRwdXQvQ09WL0NPVnNjYW5fM3BvcC9QV1NfUEgudnMuM1BvcHNfb3V0bGllcl9vdmVybGFwX2NvdjIzLnBuZyIsIHdpZHRoID0gMTAsIGhlaWdodCA9IDgsIGRwaT0zMDApCmBgYCAgICAKIVtdKC4uL091dHB1dC9DT1YvQ09Wc2Nhbl8zcG9wL1BXU19QSC52cy4zUG9wc19vdXRsaWVyX292ZXJsYXBfY292MjMucG5nKQoKCmBgYHtyIGV2YWw9RkFMU0UsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9Cgpwd3MxPC1yZWFkLmNzdigiLi4vT3V0cHV0L0NPVi9DT1ZzY2FuXzNwb3AvM3BvcHNfdG9wMXBlcmNlbnRfb3V0bGllcl9yZWdpb25zLmNvdjEzX25ldy5jc3YiKQpwd3MxPC1wd3MxW3B3czEkcG9wPT0iUFdTIiAmIHB3czEkd2luZG93PT0iMTAwayIsXQpwd3MyPC1yZWFkLmNzdigiLi4vT3V0cHV0L0NPVi8zcG9wc190b3AxcGVyY2VudF9vdXRsaWVyX3JlZ2lvbnMuY292MTMuY3N2IikKcHdzMjwtcHdzMltwd3MyJHBvcD09IlBXUyImcHdzMiR3aW5kb3c9PSIxMDBrIixdCgpwd3MxJHZjZjwtIlBIIgpwd3MyJHZjZjwtIjNQb3BzIgpwd3M8LXJiaW5kKHB3czFbLGMoImNocm9tIiwic3RhcnQiLCJlbmQiLCJjb3YxMyIsInZjZiIpXSxwd3MyWyxjKCJjaHJvbSIsInN0YXJ0IiwiZW5kIiwiY292MTMiLCJ2Y2YiKV0pCnB3cyRjaHJvbTwtZmFjdG9yKHB3cyRjaHJvbSwgbGV2ZWxzPXBhc3RlMCgiY2hyIiwgMToyNikpCmdncGxvdChkYXRhPXB3cyxhZXMoeD1zdGFydC8xMDAwMDAwLCB5PWNvdjEzLCBjb2xvcj12Y2YsIGZpbGw9dmNmKSkrCiAgICBmYWNldF93cmFwKH5jaHJvbSkrCiAgICBnZW9tX3BvaW50KHBvc2l0aW9uPXBvc2l0aW9uX2RvZGdlKHdpZHRoID0gMC43KSwgYWxwaGE9MC41KSt4bGFiKCJQb3NpdGlvbiAoTWIpIikrCiAgICBnZ3RpdGxlKCJQV1MgQ09WMTMiKQpnZ3NhdmUoIi4uL091dHB1dC9DT1YvQ09Wc2Nhbl8zcG9wL1BXU19QSC52cy4zUG9wc19vdXRsaWVyX292ZXJsYXBfY292MTMucG5nIiwgd2lkdGggPSAxMCwgaGVpZ2h0ID0gOCwgZHBpPTMwMCkKYGBgICAgIAoKIVtdKC4uL091dHB1dC9DT1YvQ09Wc2Nhbl8zcG9wL1BXU19QSC52cy4zUG9wc19vdXRsaWVyX292ZXJsYXBfY292MTMucG5nKQoKCgoKCgojIEludGVycG9wdWxhdGlvbiBjb21wYXJpc29uIHBlciB0aW1lIHBlcmlvZCAKYGBge3IgZXZhbD1GQUxTRSwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KIyMjIEludGVycG9wdWxhdGlvbiBjb21wYXJpc29ucwojZGVjb2RlIHRoZSBzYW1wbGVzIHRvIGNyZWF0ZSB0aGUgcmlnaHQgbWF0cml4CmN2PC1yZWFkLmNzdigifi9Qcm9qZWN0cy9QYWNoZXJyaW5nX1ZpbmNlbnQvTUQ3MDAwL0dXX0NvdnNfaW50ZXJQb3B1bGF0aW9uc18xMDBrXzNwb3BzLmNzdiIsIGhlYWRlciA9IEYpCmxhYnM8LXJlYWQuY3N2KCJ+L1Byb2plY3RzL1BhY2hlcnJpbmdfVmluY2VudC9NRDcwMDAvR1dfQ292c19pbnRlclBvcHVsYXRpb25zXzEwMGtfbGFiZWxzXzNwb3BzLmNzdiIgKQpsYWJzPC1sYWJzWywtMV0KY3ZtPC1kYXRhLmZyYW1lKGxhYmVsPWFzLnZlY3Rvcih0KGxhYnMpKSwgY292PWFzLnZlY3Rvcih0KGN2KSkpCgojcmVhcnJhbmdlIGJhc2VkIG9uIGNvbXBhcmlvbnM6IGNvdmFyaWFuY2UgYmV0d2VlbiBwb3B1bGF0aW9ucyB3aXRoaW4gdGhlIHNhbWUgcGVyaW9kCiNQb3BZciBTeW1ib2xzCiMgUEggMSAnUFdTJywgMTk5MQojIFBIIDIgJ1BXUycsIDE5OTYKIyBQSCAzICdQV1MnLCAyMDA2CiMgUEggNCAnUFdTJywgMjAxNwojIFBIIDUgJ1NTJywgIDE5OTEKIyBQSCA2ICdTUycsICAxOTk2CiMgUEggNyAnU1MnLCAgMjAwNgojIFBIIDggJ1NTJywgIDIwMTcKIyBQSCA5ICdUQicsICAxOTkxCiMgUEggMTAnVEInLCAgMTk5NgojIFBIIDExJ1RCJywgIDIwMDYKIyBQSCAxMidUQicsICAyMDE3CgpDb3ZzPC1kYXRhLmZyYW1lKHBvcHM9cmVwKGMoIlBXUy52cy5TUyIsICJQV1MudnMuVEIiLCAgIlNTLnZzLlRCIiksIHRpbWVzPTYpLAogICAgICAgICAgICAgICAgIHBlcmlvZD1jKHJlcCgiMTk5MS0xOTk2IiwgdGltZXM9MykscmVwKCIxOTk2LTIwMDYiLCB0aW1lcz0zKSwgcmVwKCIyMDA2LTIwMTciLCB0aW1lcz0zKSkpCgpDb3ZzJGNvdjwtYyhOQSwgY3ZtJGNvdltjdm0kbGFiZWw9PSJjb3YoUEg6IDItMSwgUEg6IDEwLTkpIl0sTkEsCiAgICAgICAgICAgIGN2bSRjb3ZbY3ZtJGxhYmVsPT0iY292KFBIOiAzLTIsIFBIOiA3LTYpIl0sY3ZtJGNvdltjdm0kbGFiZWw9PSJjb3YoUEg6IDMtMiwgUEg6IDExLTEwKSJdLCAKICAgICAgICAgICAgY3ZtJGNvdltjdm0kbGFiZWw9PSJjb3YoUEg6IDctNiwgUEg6IDExLTEwKSJdLAogICAgICAgICAgICBjdm0kY292W2N2bSRsYWJlbD09ImNvdihQSDogNC0zLCBQSDogOC03KSJdLGN2bSRjb3ZbY3ZtJGxhYmVsPT0iY292KFBIOiA0LTMsIFBIOiAxMi0xMSkiXSxjdm0kY292W2N2bSRsYWJlbD09ImNvdihQSDogOC03LCBQSDogMTItMTEpIl0pCgoKI0MuSS4KY2lzPC1yZWFkLmNzdigifi9Qcm9qZWN0cy9QYWNoZXJyaW5nX1ZpbmNlbnQvTUQ3MDAwL0dXX0NPVl9JbnRlcnBvcF9jb21wYXJpc29uX0NJcy5jc3YiKQpjaXM8LWNpc1ssLTFdCmNpbTwtZGF0YS5mcmFtZShsYWJlbD1hcy52ZWN0b3IodChsYWJzKSksIGNpX2w9YXMudmVjdG9yKHQoY2lzWzE6MTEsXSkpKQpjaW0kY2lfaDwtYXMudmVjdG9yKHQoY2lzWzEyOjIyLF0pKQoKQ292cyRjaV9sPC1hcy5udW1lcmljKGMoTkEsY2ltJGNpX2xbY2ltJGxhYmVsPT0iY292KFBIOiAyLTEsIFBIOiAxMC05KSJdLE5BLAogICAgICAgICAgICAgICAgICAgICAgY2ltJGNpX2xbY2ltJGxhYmVsPT0iY292KFBIOiAzLTIsIFBIOiA3LTYpIl0sY2ltJGNpX2xbY2ltJGxhYmVsPT0iY292KFBIOiAzLTIsIFBIOiAxMS0xMCkiXSwgY2ltJGNpX2xbY2ltJGxhYmVsPT0iY292KFBIOiA3LTYsIFBIOiAxMS0xMCkiXSwKICAgICAgICAgICAgICAgICAgICAgIGNpbSRjaV9sW2NpbSRsYWJlbD09ImNvdihQSDogNC0zLCBQSDogOC03KSJdLGNpbSRjaV9sW2NpbSRsYWJlbD09ImNvdihQSDogNC0zLCBQSDogMTItMTEpIl0sIGNpbSRjaV9sW2NpbSRsYWJlbD09ImNvdihQSDogOC03LCBQSDogMTItMTEpIl0pKQoKQ292cyRjaV9oPC1hcy5udW1lcmljKGMoTkEsIGNpbSRjaV9oW2NpbSRsYWJlbD09ImNvdihQSDogMi0xLCBQSDogMTAtOSkiXSxOQSwKICAgICAgICAgICAgICAgICAgICAgIGNpbSRjaV9oW2NpbSRsYWJlbD09ImNvdihQSDogMy0yLCBQSDogNy02KSJdLGNpbSRjaV9oW2NpbSRsYWJlbD09ImNvdihQSDogMy0yLCBQSDogMTEtMTApIl0sIGNpbSRjaV9oW2NpbSRsYWJlbD09ImNvdihQSDogNy02LCBQSDogMTEtMTApIl0sCiAgICAgICAgICAgICAgICAgICAgICBjaW0kY2lfaFtjaW0kbGFiZWw9PSJjb3YoUEg6IDQtMywgUEg6IDgtNykiXSxjaW0kY2lfaFtjaW0kbGFiZWw9PSJjb3YoUEg6IDQtMywgUEg6IDEyLTExKSJdLCBjaW0kY2lfaFtjaW0kbGFiZWw9PSJjb3YoUEg6IDgtNywgUEg6IDEyLTExKSJdKSkKCiNCYXJwbG90CmdncGxvdChDb3ZzLCBhZXMoeD1wZXJpb2QsIHk9Y292LCBmaWxsPXBvcHMpKSsKICAgIGdlb21fYmFyKHN0YXQ9ImlkZW50aXR5Iixwb3NpdGlvbj1wb3NpdGlvbl9kb2RnZSh3aWR0aCA9IDAuNyksIHdpZHRoPTAuOCkrCiAgICB5bGFiKCJDb3ZhcmlhbmNlIikreGxhYignJykrdGhlbWVfY2xhc3NpYygpKwogICAgZ2VvbV9obGluZSh5aW50ZXJjZXB0ID0gMCxjb2xvcj0iZ3JheTcwIiwgc2l6ZT0wLjMpKwogICAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzPWNvbHNbYygyLDEsMyldKSsKICAgIHRoZW1lKGxlZ2VuZC50aXRsZSA9IGVsZW1lbnRfYmxhbmsoKSkrCiAgICBzY2FsZV95X2NvbnRpbnVvdXMobGFiZWxzID0gY29tbWEpKwogICAgeWxpbSgtMC4wMDEzLCAwLjAwMikrCiAgICBnZW9tX2Vycm9yYmFyKGFlcyh5bWluPWNpX2wsIHltYXg9Y2lfaCksIHdpZHRoPS4yLCBzaXplPS4yLCBwb3NpdGlvbj1wb3NpdGlvbl9kb2RnZSh3aWR0aCA9IDAuNykpCmdnc2F2ZSgiLi4vT3V0cHV0L0NPVi9JbnRlcnBvcF9jb3ZfY29tcGFyaXNvbl8zUG9wc19uZXcucG5nIix3aWR0aCA9IDQuNywgaGVpZ2h0ID0gMywgZHBpPTMwMCkKCiNQb2ludCBwbG90CmdncGxvdChDb3ZzLCBhZXMoeD1wZXJpb2QsIHk9Y292LCBjb2xvcj1wb3BzKSkrCiAgICBnZW9tX3BvaW50KHBvc2l0aW9uPXBvc2l0aW9uX2RvZGdlKHdpZHRoID0gMC43KSwgc2l6ZT00KSsKICAgIHlsYWIoIkNvdmFyaWFuY2UiKSt4bGFiKCcnKSt0aGVtZV9jbGFzc2ljKCkrCiAgICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQgPSAwLGNvbG9yPSJncmF5NzAiLCBzaXplPTAuMykrCiAgICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzPWNvbHNbYygyLDEsMyldKSsKICAgIHRoZW1lKGxlZ2VuZC50aXRsZSA9IGVsZW1lbnRfYmxhbmsoKSkrCiAgICBzY2FsZV95X2NvbnRpbnVvdXMobGFiZWxzID0gY29tbWEpKwogICAgZ2VvbV9lcnJvcmJhcihhZXMoeW1pbj1jaV9sLCB5bWF4PWNpX2gpLCB3aWR0aD0uMiwgc2l6ZT0uMiwgcG9zaXRpb249cG9zaXRpb25fZG9kZ2Uod2lkdGggPSAwLjcpKSsKICAgIHlsaW0oLTAuMDAxMywgMC4wMDIpKwogICAgIGdlb21fdmxpbmUoeGludGVyY2VwdCA9IGMoMS41LDIuNSksIGNvbG9yPSJncmF5Iiwgc2l6ZT0wLjMpCmdnc2F2ZSgiLi4vT3V0cHV0L0NPVi9JbnRlcnBvcF9jb3ZfY29tcGFyaXNvbl8zUG9wc19uZXdfUG9pbnRQbG90LnBuZyIsd2lkdGggPSA0LjcsIGhlaWdodCA9IDMsIGRwaT0zMDApCgojbGluZSBwbG90CkNvdnMkdGltZTwtMQpDb3ZzJHRpbWVbQ292cyRwZXJpb2Q9PSIxOTk2LTIwMDYiXTwtMgpDb3ZzJHRpbWVbQ292cyRwZXJpb2Q9PSIyMDA2LTIwMTciXTwtMwpDb3ZzPC1Db3ZzW29yZGVyKENvdnMkdGltZSksXQpnZ3Bsb3QoQ292cywgYWVzKHg9dGltZSwgeT1jb3YsIGNvbG9yPXBvcHMsIGdyb3VwPXBvcHMpKSsKICAgIGdlb21fcG9pbnQocG9zaXRpb249cG9zaXRpb25fZG9kZ2Uod2lkdGggPSAwLjcpLCBzaXplPTQpKwogICAgZ2VvbV9wYXRoKHBvc2l0aW9uPXBvc2l0aW9uX2RvZGdlKHdpZHRoID0gMC43KSkrCiAgICB5bGFiKCJDb3ZhcmlhbmNlIikreGxhYignJykrdGhlbWVfY2xhc3NpYygpKwogICAgZ2VvbV9obGluZSh5aW50ZXJjZXB0ID0gMCxjb2xvcj0iZ3JheTcwIiwgc2l6ZT0wLjMpKwogICAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcz1jb2xzW2MoMiwxLDMpXSkrCiAgICB0aGVtZShsZWdlbmQudGl0bGUgPSBlbGVtZW50X2JsYW5rKCkpKwogICAgc2NhbGVfeV9jb250aW51b3VzKGxhYmVscyA9IGNvbW1hKSsKICAgIGdlb21fZXJyb3JiYXIoYWVzKHltaW49Y2lfbCwgeW1heD1jaV9oKSwgd2lkdGg9LjIsIHNpemU9LjIsIHBvc2l0aW9uPXBvc2l0aW9uX2RvZGdlKHdpZHRoID0gMC43KSkrCiAgICB5bGltKC0wLjAwMTMsIDAuMDAyKSsKICAgICBnZW9tX3ZsaW5lKHhpbnRlcmNlcHQgPSBjKDEuNSwyLjUpLCBjb2xvcj0iZ3JheSIsIHNpemU9MC4zKSsKICAgIHNjYWxlX3hfY29udGludW91cyhicmVha3M9YygxLDIsMyksIGxhYmVscyA9IGMoIjE5OTEtMTk5NiIsIjE5OTYtMjAwNiIsIjIwMDYtMjAxNyIpKQpnZ3NhdmUoIi4uL091dHB1dC9DT1YvSW50ZXJwb3BfY292X2NvbXBhcmlzb25fM1BvcHNfbmV3X0xpbmVQbG90LnBuZyIsd2lkdGggPSA0LjcsIGhlaWdodCA9IDMsIGRwaT0zMDApCgpgYGAKCiFbXSguLi9PdXRwdXQvQ09WL0ludGVycG9wX2Nvdl9jb21wYXJpc29uXzNQb3BzX25ld19Qb2ludFBsb3QucG5nKQoKIyMgTG9uZ2VyIHRpbWUgcGVyaW9kCmBgYHtyIGV2YWw9RkFMU0UsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CiMjIExvbmdlciB0aW1lLXBlcmlvZApDb3ZzMjwtZGF0YS5mcmFtZShwb3BzPXJlcChjKCJQV1MudnMuU1MiLCAiUFdTLnZzLlRCIiwgICJTUy52cy5UQiIpLCB0aW1lcz0zKSwKICAgICAgICAgICAgICAgICBwZXJpb2Q9YyhyZXAoIjE5OTEtMjAwNiIsIHRpbWVzPTMpLHJlcCgiMTk5MS0yMDE3IiwgdGltZXM9MykscmVwKCIxOTk2LTIwMTciLCB0aW1lcz0zKSkpCgpjdjE8LXJlYWQuY3N2KCJ+L1Byb2plY3RzL1BhY2hlcnJpbmdfVmluY2VudC9NRDcwMDAvR1dfQ292c19pbnRlclBvcHVsYXRpb25zXzEwMGtfMTk5MS0yMDA2LmNzdiIsIGhlYWRlciA9IEYpCmxhYnMxPC1yZWFkLmNzdigifi9Qcm9qZWN0cy9QYWNoZXJyaW5nX1ZpbmNlbnQvTUQ3MDAwL0dXX0NvdnNfaW50ZXJQb3B1bGF0aW9uc18xMDBrX2xhYmVsc18xOTkxLTIwMDYuY3N2IiApCmxhYnMxPC1sYWJzMVssLTFdCmN2bTE8LWRhdGEuZnJhbWUobGFiZWw9YXMudmVjdG9yKHQobGFiczEpKSwgY292PWFzLnZlY3Rvcih0KGN2MSkpKQoKY3YyPC1yZWFkLmNzdigifi9Qcm9qZWN0cy9QYWNoZXJyaW5nX1ZpbmNlbnQvTUQ3MDAwL0dXX0NvdnNfaW50ZXJQb3B1bGF0aW9uc18xMDBrXzE5OTEtMjAxNy5jc3YiLCBoZWFkZXIgPSBGKQpsYWJzMjwtcmVhZC5jc3YoIn4vUHJvamVjdHMvUGFjaGVycmluZ19WaW5jZW50L01ENzAwMC9HV19Db3ZzX2ludGVyUG9wdWxhdGlvbnNfMTAwa19sYWJlbHNfMTk5MS0yMDE3LmNzdiIgKQpsYWJzMjwtbGFiczJbLC0xXQpjdm0yPC1kYXRhLmZyYW1lKGxhYmVsPWFzLnZlY3Rvcih0KGxhYnMyKSksIGNvdj1hcy52ZWN0b3IodChjdjIpKSkKCmN2MzwtcmVhZC5jc3YoIn4vUHJvamVjdHMvUGFjaGVycmluZ19WaW5jZW50L01ENzAwMC9HV19Db3ZzX2ludGVyUG9wdWxhdGlvbnNfMTAwa18xOTk2LTIwMTcuY3N2IiwgaGVhZGVyID0gRikKbGFiczM8LXJlYWQuY3N2KCJ+L1Byb2plY3RzL1BhY2hlcnJpbmdfVmluY2VudC9NRDcwMDAvR1dfQ292c19pbnRlclBvcHVsYXRpb25zXzEwMGtfbGFiZWxzXzE5OTYtMjAxNy5jc3YiICkKbGFiczM8LWxhYnMzWywtMV0KY3ZtMzwtZGF0YS5mcmFtZShsYWJlbD1hcy52ZWN0b3IodChsYWJzMykpLCBjb3Y9YXMudmVjdG9yKHQoY3YzKSkpCgpDb3ZzMiRjb3Y8LWMoTkEsIGN2bTEkY292W2N2bTEkbGFiZWw9PSJjb3YoUEg6IDItMSwgUEg6IDQtMykiXSwgTkEsCiAgICAgICAgICAgICBOQSwgY3ZtMiRjb3ZbY3ZtMiRsYWJlbD09ImNvdihQSDogMi0xLCBQSDogNC0zKSJdLCBOQSwKICAgICAgICAgICAgIGN2bTMkY292W2N2bTMkbGFiZWw9PSJjb3YoUEg6IDItMSwgUEg6IDQtMykiXSwgY3ZtMyRjb3ZbY3ZtMyRsYWJlbD09ImNvdihQSDogMi0xLCBQSDogNi01KSJdLCBjdm0zJGNvdltjdm0zJGxhYmVsPT0iY292KFBIOiA0LTMsIFBIOiA2LTUpIl0pCgojQy5JLgpjaXMxPC1yZWFkLmNzdigifi9Qcm9qZWN0cy9QYWNoZXJyaW5nX1ZpbmNlbnQvTUQ3MDAwL0dXX0NPVl9JbnRlcnBvcF9jb21wYXJpc29uX0NJc18xOTkxLTIwMDYuY3N2IikKY2lzMTwtY2lzMVssLTFdCmNpczI8LXJlYWQuY3N2KCJ+L1Byb2plY3RzL1BhY2hlcnJpbmdfVmluY2VudC9NRDcwMDAvR1dfQ09WX0ludGVycG9wX2NvbXBhcmlzb25fQ0lzXzE5OTEtMjAxNy5jc3YiKQpjaXMyPC1jaXMyWywtMV0KY2lzMzwtcmVhZC5jc3YoIn4vUHJvamVjdHMvUGFjaGVycmluZ19WaW5jZW50L01ENzAwMC9HV19DT1ZfSW50ZXJwb3BfY29tcGFyaXNvbl9DSXNfMTk5Ni0yMDE3LmNzdiIpCmNpczM8LWNpczNbLC0xXQoKI2NpbTwtZGF0YS5mcmFtZShsYWJlbD1hcy52ZWN0b3IodChsYWJzKSksIGNpX2w9YXMudmVjdG9yKHQoY2lzMVsxOjQsXSkpKQojY2ltJGNpX2g8LWFzLnZlY3Rvcih0KGNpc1sxMjoyMixdKSkKCkNvdnMyJGNpX2w8LWFzLm51bWVyaWMoYyhOQSxjaXMxWzEsM10sTkEsCiAgICAgICAgICAgICAgICAgICAgICAgIE5BLGNpczJbMSwzXSxOQSwKICAgICAgICAgICAgICAgICAgICAgIGNpczNbMSwzXSxjaXMzWzEsNV0sY2lzM1szLDVdKSkKCkNvdnMyJGNpX2g8LWFzLm51bWVyaWMoYyhOQSxjaXMxWzQsM10sTkEsCiAgICAgICAgICAgICAgICAgICAgICAgIE5BLGNpczJbNCwzXSxOQSwKICAgICAgICAgICAgICAgICAgICAgIGNpczNbNiwzXSxjaXMzWzYsNV0sY2lzM1s4LDVdKSkKCgpnZ3Bsb3QoQ292czIsIGFlcyh4PXBlcmlvZCwgeT1jb3YsIGZpbGw9cG9wcykpKwogICAgZ2VvbV9iYXIoc3RhdD0iaWRlbnRpdHkiLHBvc2l0aW9uPXBvc2l0aW9uX2RvZGdlKHdpZHRoID0gMC43KSwgd2lkdGg9MC44KSsKICAgIHlsYWIoIkNvdmFyaWFuY2UiKSt4bGFiKCcnKSt0aGVtZV9jbGFzc2ljKCkrCiAgICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQgPSAwLGNvbG9yPSJncmF5NzAiLCBzaXplPTAuMykrCiAgICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXM9Y29sc1tjKDIsMSwzKV0pKwogICAgdGhlbWUobGVnZW5kLnRpdGxlID0gZWxlbWVudF9ibGFuaygpKStzY2FsZV95X2NvbnRpbnVvdXMobGFiZWxzID0gY29tbWEpKwogICAgeWxpbSgtMC4wMDEzLCAwLjAwMikrCiAgICBnZW9tX2Vycm9yYmFyKGFlcyh5bWluPWNpX2wsIHltYXg9Y2lfaCksIHdpZHRoPS4yLCBzaXplPS4yLCBwb3NpdGlvbj1wb3NpdGlvbl9kb2RnZSh3aWR0aCA9IDAuNykpCmdnc2F2ZSgiLi4vT3V0cHV0L0NPVi9JbnRlcnBvcF9jb3ZfY29tcGFyaXNvbl8zUG9wc19Mb25vZ2VyUGVyaW9kLnBuZyIsd2lkdGggPSA0LjcsIGhlaWdodCA9IDMsIGRwaT0zMDApCgpnZ3Bsb3QoQ292czIsIGFlcyh4PXBlcmlvZCwgeT1jb3YsIGNvbG9yPXBvcHMpKSsKICAgIGdlb21fcG9pbnQocG9zaXRpb249cG9zaXRpb25fZG9kZ2Uod2lkdGggPSAwLjcpLCBzaXplPTQpKwogICAgeWxhYigiQ292YXJpYW5jZSIpK3hsYWIoJycpK3RoZW1lX2NsYXNzaWMoKSsKICAgIGdlb21faGxpbmUoeWludGVyY2VwdCA9IDAsY29sb3I9ImdyYXk3MCIsIHNpemU9MC4zKSsKICAgIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXM9Y29sc1tjKDIsMSwzKV0pKwogICAgdGhlbWUobGVnZW5kLnRpdGxlID0gZWxlbWVudF9ibGFuaygpKSsKICAgIHNjYWxlX3lfY29udGludW91cyhsYWJlbHMgPSBjb21tYSkrCiAgICAgeWxpbSgtMC4wMDEzLCAwLjAwMikrCiAgICBnZW9tX2Vycm9yYmFyKGFlcyh5bWluPWNpX2wsIHltYXg9Y2lfaCksIHdpZHRoPS4yLCBzaXplPS4yLCBwb3NpdGlvbj1wb3NpdGlvbl9kb2RnZSh3aWR0aCA9IDAuNykpKwogICAgZ2VvbV92bGluZSh4aW50ZXJjZXB0ID0gYygxLjUsMi41KSwgY29sb3I9ImdyYXkiLCBzaXplPTAuMykKZ2dzYXZlKCIuLi9PdXRwdXQvQ09WL0ludGVycG9wX2Nvdl9jb21wYXJpc29uXzNQb3BzTG9ub2dlclBlcmlvZF9Qb2ludFBsb3QucG5nIix3aWR0aCA9IDQuNywgaGVpZ2h0ID0gMywgZHBpPTMwMCkKCgpgYGAKIVtdKC4uL091dHB1dC9DT1YvSW50ZXJwb3BfY292X2NvbXBhcmlzb25fM1BvcHNMb25vZ2VyUGVyaW9kX1BvaW50UGxvdC5wbmcpCgojIEZvY3VzZWQgZnJlcSBhbmFseXNpcwojIyByZWwgZ2VuZSAoY2hyMTM6IDIzMDcwMDAwIC0gMjMwODAwMDApCgpgYGB7ciBldmFsPUZBTFNFLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQpwb3BzPC1jKCJQV1M5MSIsIlBXUzk2IiwiUFdTMDciLCJQV1MxNyIpCnlyPC1jKDE5OTEsMTk5NiwyMDA3LDIwMTcpCm1hZjwtZGF0YS5mcmFtZSgpCmZvciAoaSBpbiAxOjQpewogICAgYWY8LXJlYWQudGFibGUocGFzdGUwKCIuLi9EYXRhL25ld192Y2YvQUYvIixwb3BzW2ldLCIubWFmcyIpLHNlcD0iXHQiLCBoZWFkZXIgPSBUKQogICAgYWY8LWFmW2FmJGNocm9tbz09ImNocjEzIiZhZiRwb3NpdGlvbj49MjMwNzAwMDAmYWYkcG9zaXRpb248PTIzMDgwMDAwLF0KICAgIGFmJHllYXI8LXlyW2ldCiAgICBtYWY8LXJiaW5kKG1hZixhZikKfQojd3JpdGUuY3N2KG1hZiwiLi4vT3V0cHV0L0NPVi9DT1ZzY2FuXzNwb3AvQUZfbWFmX2NocjEzXzIzTWIuY3N2IikKCmdncGxvdChtYWYsIGFlcyh4PXllYXIsIHk9a25vd25FTSwgY29sb3I9ZmFjdG9yKHBvc2l0aW9uKSkpKwogICAgZ2VvbV9wb2ludCgpKwogICAgZ2VvbV9wYXRoKCkrZ2d0aXRsZSgiTUFGIChBTkdTRCkiKSsKICAgIHlsYWIoIm1hZiIpKwogICAgdGhlbWUobGVnZW5kLnRpdGxlPWVsZW1lbnRfYmxhbmsoKSkKZ2dzYXZlKCIuLi9PdXRwdXQvQ09WL0NPVnNjYW4vQUZfY2gxM18yMy4wNy0yMy4wOF9hbmdzZC5wbmciLCB3aWR0aCA9IDUsIGhlaWdodD0zLCBkcGk9MzAwKQoKCkFGPC1kYXRhLmZyYW1lKCkKZm9yIChpIGluIDE6NCl7CiAgICBhZjwtcmVhZC50YWJsZShwYXN0ZTAoIi4uL0RhdGEvbmV3X3ZjZi9BRi8iLHBvcHNbaV0sIl9tYWYwNV9hZi5mcnEiKSxoZWFkZXIgPSBGQUxTRSwgc2tpcD0xLCBjb2wubmFtZXMgPSBjKCJjaHIiLCJwb3MiLCJuX2FsbGVsZSIsIm5fc2FtcGxlIiwiTWFqb3JBRiIsIk1BRiIpKQogICAgYWY8LWFmW2FmJGNocj09ImNocjEzIiZhZiRwb3M+PTIzMDcwMDAwJmFmJHBvczw9MjMwODAwMDAsXQogICAgYWYkeWVhcjwteXJbaV0KICAgIGFmJG1hZjwtc3Vic3RyKGFmJE1BRiwgMywxMCkKICAgIGFmJG1hZjwtYXMubnVtZXJpYyhhZiRtYWYpCiAgICBhZjwtYWZbLGMoImNociIsInBvcyIsIm1hZiIsInllYXIiKV0KICAgIEFGPC1yYmluZChBRixhZikKfQpnZ3Bsb3QoQUYsIGFlcyh4PXllYXIsIHk9bWFmLCBjb2xvcj1mYWN0b3IocG9zKSkpKwogICAgZ2VvbV9wb2ludCgpKwogICAgZ2VvbV9wYXRoKCkrZ2d0aXRsZSgiTUFGICh2Y2Z0b29scykiKSsKICAgIHRoZW1lKGxlZ2VuZC50aXRsZT1lbGVtZW50X2JsYW5rKCkpCmdnc2F2ZSgiLi4vT3V0cHV0L0NPVi9DT1ZzY2FuL0FGX2NoMTNfMjMuMDctMjMuMDgucG5nIiwgd2lkdGggPSA1LCBoZWlnaHQ9MywgZHBpPTMwMCkKCgojIyNUQgpwb3BzPC1jKCJUQjkxIiwiVEI5NiIsIlRCMDYiLCJUQjE3IiwiUFdTOTEiLCJQV1M5NiIsIlBXUzA3IiwiUFdTMTciLCJTUzk2IiwiU1MwNiIsIlNTMTciKQp5cjwtYygxOTkxLDE5OTYsMjAwNiwyMDE3LDE5OTEsMTk5NiwyMDA3LDIwMTcsMTk5NiwyMDA2LDIwMTcpCm1hZjwtZGF0YS5mcmFtZSgpCmZvciAoaSBpbiAxOmxlbmd0aChwb3BzKSl7CiAgICBhZjwtcmVhZC50YWJsZShwYXN0ZTAoIi4uL0RhdGEvbmV3X3ZjZi9BRi8iLHBvcHNbaV0sIi5tYWZzIiksc2VwPSJcdCIsIGhlYWRlciA9IFQpCiAgICBhZjwtYWZbYWYkY2hyb21vPT0iY2hyMTMiJmFmJHBvc2l0aW9uPj0yMzA3MDAwMCZhZiRwb3NpdGlvbjw9MjMwODAwMDAsXQogICAgYWYkeWVhcjwteXJbaV0KICAgIGFmJHBvcDwtc3ViKCJcXGRcXGQiLCIiLCBwb3BzW2ldKQogICAgbWFmPC1yYmluZChtYWYsYWYpCn0KI3dyaXRlLmNzdihtYWYsIi4uL091dHB1dC9DT1YvQ09Wc2Nhbl8zcG9wL0FGX21hZl9jaHIxM18yM01iLmNzdiIpCmdncGxvdChtYWYsIGFlcyh4PXllYXIsIHk9a25vd25FTSwgY29sb3I9cG9wKSkrCiAgICBmYWNldF93cmFwKH5mYWN0b3IocG9zaXRpb24pKSsKICAgIGdlb21fcG9pbnQoKSsKICAgIGdlb21fcGF0aCgpK2dndGl0bGUoIkNocjEzIChyZWwgZ2VuZSkiKSsKICAgIHlsYWIoIm1hZiIpKwogICAgdGhlbWUobGVnZW5kLnRpdGxlPWVsZW1lbnRfYmxhbmsoKSkKZ2dzYXZlKCIuLi9PdXRwdXQvQ09WL0NPVnNjYW4vQUZfY2gxM18yMy4wNy0yMy4wOF9hbmdzZC5wbmciLCB3aWR0aCA9IDUsIGhlaWdodD0zLCBkcGk9MzAwKQoKCgoKYGBgCiFbXSguLi9PdXRwdXQvQ09WL0NPVnNjYW4vQUZfY2gxM18yMy4wNy0yMy4wOF9hbmdzZC5wbmcpCgoKCgoKYGBge3IgZXZhbD1GQUxTRSwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KCgoKCmBgYAoKYGBge3IgZXZhbD1GQUxTRSwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KYGBgCgo=